• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "bcc/Renderscript/RSUtils.h"
20 
21 #include <cstdlib>
22 #include <functional>
23 #include <unordered_set>
24 
25 #include <llvm/IR/DerivedTypes.h>
26 #include <llvm/IR/Function.h>
27 #include <llvm/IR/Instructions.h>
28 #include <llvm/IR/IRBuilder.h>
29 #include <llvm/IR/MDBuilder.h>
30 #include <llvm/IR/Module.h>
31 #include <llvm/Pass.h>
32 #include <llvm/Support/raw_ostream.h>
33 #include <llvm/IR/DataLayout.h>
34 #include <llvm/IR/Function.h>
35 #include <llvm/IR/Type.h>
36 #include <llvm/Transforms/Utils/BasicBlockUtils.h>
37 
38 #include "bcc/Config/Config.h"
39 #include "bcc/Support/Log.h"
40 
41 #include "bcinfo/MetadataExtractor.h"
42 
43 #ifndef __DISABLE_ASSERTS
44 // Only used in bccAssert()
45 const int kNumExpandedForeachParams = 4;
46 const int kNumExpandedReduceAccumulatorParams = 4;
47 #endif
48 
49 const char kRenderScriptTBAARootName[] = "RenderScript Distinct TBAA";
50 const char kRenderScriptTBAANodeName[] = "RenderScript TBAA";
51 
52 using namespace bcc;
53 
54 namespace {
55 
56 static const bool gEnableRsTbaa = true;
57 
58 /* RSKernelExpandPass - This pass operates on functions that are able
59  * to be called via rsForEach(), "foreach_<NAME>", or
60  * "reduce_<NAME>". We create an inner loop for the function to be
61  * invoked over the appropriate data cells of the input/output
62  * allocations (adjusting other relevant parameters as we go). We
63  * support doing this for any forEach or reduce style compute
64  * kernels. The new function name is the original function name
65  * followed by ".expand". Note that we still generate code for the
66  * original function.
67  */
68 class RSKernelExpandPass : public llvm::ModulePass {
69 public:
70   static char ID;
71 
72 private:
73   static const size_t RS_KERNEL_INPUT_LIMIT = 8; // see frameworks/base/libs/rs/cpu_ref/rsCpuCoreRuntime.h
74 
75   typedef std::unordered_set<llvm::Function *> FunctionSet;
76 
77   enum RsLaunchDimensionsField {
78     RsLaunchDimensionsFieldX,
79     RsLaunchDimensionsFieldY,
80     RsLaunchDimensionsFieldZ,
81     RsLaunchDimensionsFieldLod,
82     RsLaunchDimensionsFieldFace,
83     RsLaunchDimensionsFieldArray,
84 
85     RsLaunchDimensionsFieldCount
86   };
87 
88   enum RsExpandKernelDriverInfoPfxField {
89     RsExpandKernelDriverInfoPfxFieldInPtr,
90     RsExpandKernelDriverInfoPfxFieldInStride,
91     RsExpandKernelDriverInfoPfxFieldInLen,
92     RsExpandKernelDriverInfoPfxFieldOutPtr,
93     RsExpandKernelDriverInfoPfxFieldOutStride,
94     RsExpandKernelDriverInfoPfxFieldOutLen,
95     RsExpandKernelDriverInfoPfxFieldDim,
96     RsExpandKernelDriverInfoPfxFieldCurrent,
97     RsExpandKernelDriverInfoPfxFieldUsr,
98     RsExpandKernelDriverInfoPfxFieldUsLenr,
99 
100     RsExpandKernelDriverInfoPfxFieldCount
101   };
102 
103   llvm::Module *Module;
104   llvm::LLVMContext *Context;
105 
106   /*
107    * Pointers to LLVM type information for the the function signatures
108    * for expanded functions. These must be re-calculated for each module
109    * the pass is run on.
110    */
111   llvm::FunctionType *ExpandedForEachType;
112   llvm::Type *RsExpandKernelDriverInfoPfxTy;
113 
114   uint32_t mExportForEachCount;
115   const char **mExportForEachNameList;
116   const uint32_t *mExportForEachSignatureList;
117 
118   // Turns on optimization of allocation stride values.
119   bool mEnableStepOpt;
120 
getRootSignature(llvm::Function * Function)121   uint32_t getRootSignature(llvm::Function *Function) {
122     const llvm::NamedMDNode *ExportForEachMetadata =
123         Module->getNamedMetadata("#rs_export_foreach");
124 
125     if (!ExportForEachMetadata) {
126       llvm::SmallVector<llvm::Type*, 8> RootArgTys;
127       for (llvm::Function::arg_iterator B = Function->arg_begin(),
128                                         E = Function->arg_end();
129            B != E;
130            ++B) {
131         RootArgTys.push_back(B->getType());
132       }
133 
134       // For pre-ICS bitcode, we may not have signature information. In that
135       // case, we use the size of the RootArgTys to select the number of
136       // arguments.
137       return (1 << RootArgTys.size()) - 1;
138     }
139 
140     if (ExportForEachMetadata->getNumOperands() == 0) {
141       return 0;
142     }
143 
144     bccAssert(ExportForEachMetadata->getNumOperands() > 0);
145 
146     // We only handle the case for legacy root() functions here, so this is
147     // hard-coded to look at only the first such function.
148     llvm::MDNode *SigNode = ExportForEachMetadata->getOperand(0);
149     if (SigNode != nullptr && SigNode->getNumOperands() == 1) {
150       llvm::Metadata *SigMD = SigNode->getOperand(0);
151       if (llvm::MDString *SigS = llvm::dyn_cast<llvm::MDString>(SigMD)) {
152         llvm::StringRef SigString = SigS->getString();
153         uint32_t Signature = 0;
154         if (SigString.getAsInteger(10, Signature)) {
155           ALOGE("Non-integer signature value '%s'", SigString.str().c_str());
156           return 0;
157         }
158         return Signature;
159       }
160     }
161 
162     return 0;
163   }
164 
isStepOptSupported(llvm::Type * AllocType)165   bool isStepOptSupported(llvm::Type *AllocType) {
166 
167     llvm::PointerType *PT = llvm::dyn_cast<llvm::PointerType>(AllocType);
168     llvm::Type *VoidPtrTy = llvm::Type::getInt8PtrTy(*Context);
169 
170     if (mEnableStepOpt) {
171       return false;
172     }
173 
174     if (AllocType == VoidPtrTy) {
175       return false;
176     }
177 
178     if (!PT) {
179       return false;
180     }
181 
182     // remaining conditions are 64-bit only
183     if (VoidPtrTy->getPrimitiveSizeInBits() == 32) {
184       return true;
185     }
186 
187     // coerce suggests an upconverted struct type, which we can't support
188     if (AllocType->getStructName().find("coerce") != llvm::StringRef::npos) {
189       return false;
190     }
191 
192     // 2xi64 and i128 suggest an upconverted struct type, which are also unsupported
193     llvm::Type *V2xi64Ty = llvm::VectorType::get(llvm::Type::getInt64Ty(*Context), 2);
194     llvm::Type *Int128Ty = llvm::Type::getIntNTy(*Context, 128);
195     if (AllocType == V2xi64Ty || AllocType == Int128Ty) {
196       return false;
197     }
198 
199     return true;
200   }
201 
202   // Get the actual value we should use to step through an allocation.
203   //
204   // Normally the value we use to step through an allocation is given to us by
205   // the driver. However, for certain primitive data types, we can derive an
206   // integer constant for the step value. We use this integer constant whenever
207   // possible to allow further compiler optimizations to take place.
208   //
209   // DL - Target Data size/layout information.
210   // T - Type of allocation (should be a pointer).
211   // OrigStep - Original step increment (root.expand() input from driver).
getStepValue(llvm::DataLayout * DL,llvm::Type * AllocType,llvm::Value * OrigStep)212   llvm::Value *getStepValue(llvm::DataLayout *DL, llvm::Type *AllocType,
213                             llvm::Value *OrigStep) {
214     bccAssert(DL);
215     bccAssert(AllocType);
216     bccAssert(OrigStep);
217     llvm::PointerType *PT = llvm::dyn_cast<llvm::PointerType>(AllocType);
218     if (isStepOptSupported(AllocType)) {
219       llvm::Type *ET = PT->getElementType();
220       uint64_t ETSize = DL->getTypeAllocSize(ET);
221       llvm::Type *Int32Ty = llvm::Type::getInt32Ty(*Context);
222       return llvm::ConstantInt::get(Int32Ty, ETSize);
223     } else {
224       return OrigStep;
225     }
226   }
227 
228   /// Builds the types required by the pass for the given context.
buildTypes(void)229   void buildTypes(void) {
230     // Create the RsLaunchDimensionsTy and RsExpandKernelDriverInfoPfxTy structs.
231 
232     llvm::Type *Int8Ty                   = llvm::Type::getInt8Ty(*Context);
233     llvm::Type *Int8PtrTy                = Int8Ty->getPointerTo();
234     llvm::Type *Int8PtrArrayInputLimitTy = llvm::ArrayType::get(Int8PtrTy, RS_KERNEL_INPUT_LIMIT);
235     llvm::Type *Int32Ty                  = llvm::Type::getInt32Ty(*Context);
236     llvm::Type *Int32ArrayInputLimitTy   = llvm::ArrayType::get(Int32Ty, RS_KERNEL_INPUT_LIMIT);
237     llvm::Type *VoidPtrTy                = llvm::Type::getInt8PtrTy(*Context);
238     llvm::Type *Int32Array4Ty            = llvm::ArrayType::get(Int32Ty, 4);
239 
240     /* Defined in frameworks/base/libs/rs/cpu_ref/rsCpuCore.h:
241      *
242      * struct RsLaunchDimensions {
243      *   uint32_t x;
244      *   uint32_t y;
245      *   uint32_t z;
246      *   uint32_t lod;
247      *   uint32_t face;
248      *   uint32_t array[4];
249      * };
250      */
251     llvm::SmallVector<llvm::Type*, RsLaunchDimensionsFieldCount> RsLaunchDimensionsTypes;
252     RsLaunchDimensionsTypes.push_back(Int32Ty);       // uint32_t x
253     RsLaunchDimensionsTypes.push_back(Int32Ty);       // uint32_t y
254     RsLaunchDimensionsTypes.push_back(Int32Ty);       // uint32_t z
255     RsLaunchDimensionsTypes.push_back(Int32Ty);       // uint32_t lod
256     RsLaunchDimensionsTypes.push_back(Int32Ty);       // uint32_t face
257     RsLaunchDimensionsTypes.push_back(Int32Array4Ty); // uint32_t array[4]
258     llvm::StructType *RsLaunchDimensionsTy =
259         llvm::StructType::create(RsLaunchDimensionsTypes, "RsLaunchDimensions");
260 
261     /* Defined as the beginning of RsExpandKernelDriverInfo in frameworks/base/libs/rs/cpu_ref/rsCpuCoreRuntime.h:
262      *
263      * struct RsExpandKernelDriverInfoPfx {
264      *     const uint8_t *inPtr[RS_KERNEL_INPUT_LIMIT];
265      *     uint32_t inStride[RS_KERNEL_INPUT_LIMIT];
266      *     uint32_t inLen;
267      *
268      *     uint8_t *outPtr[RS_KERNEL_INPUT_LIMIT];
269      *     uint32_t outStride[RS_KERNEL_INPUT_LIMIT];
270      *     uint32_t outLen;
271      *
272      *     // Dimension of the launch
273      *     RsLaunchDimensions dim;
274      *
275      *     // The walking iterator of the launch
276      *     RsLaunchDimensions current;
277      *
278      *     const void *usr;
279      *     uint32_t usrLen;
280      *
281      *     // Items below this line are not used by the compiler and can be change in the driver.
282      *     // So the compiler must assume there are an unknown number of fields of unknown type
283      *     // beginning here.
284      * };
285      *
286      * The name "RsExpandKernelDriverInfoPfx" is known to RSInvariantPass (RSInvariant.cpp).
287      */
288     llvm::SmallVector<llvm::Type*, RsExpandKernelDriverInfoPfxFieldCount> RsExpandKernelDriverInfoPfxTypes;
289     RsExpandKernelDriverInfoPfxTypes.push_back(Int8PtrArrayInputLimitTy); // const uint8_t *inPtr[RS_KERNEL_INPUT_LIMIT]
290     RsExpandKernelDriverInfoPfxTypes.push_back(Int32ArrayInputLimitTy);   // uint32_t inStride[RS_KERNEL_INPUT_LIMIT]
291     RsExpandKernelDriverInfoPfxTypes.push_back(Int32Ty);                  // uint32_t inLen
292     RsExpandKernelDriverInfoPfxTypes.push_back(Int8PtrArrayInputLimitTy); // uint8_t *outPtr[RS_KERNEL_INPUT_LIMIT]
293     RsExpandKernelDriverInfoPfxTypes.push_back(Int32ArrayInputLimitTy);   // uint32_t outStride[RS_KERNEL_INPUT_LIMIT]
294     RsExpandKernelDriverInfoPfxTypes.push_back(Int32Ty);                  // uint32_t outLen
295     RsExpandKernelDriverInfoPfxTypes.push_back(RsLaunchDimensionsTy);     // RsLaunchDimensions dim
296     RsExpandKernelDriverInfoPfxTypes.push_back(RsLaunchDimensionsTy);     // RsLaunchDimensions current
297     RsExpandKernelDriverInfoPfxTypes.push_back(VoidPtrTy);                // const void *usr
298     RsExpandKernelDriverInfoPfxTypes.push_back(Int32Ty);                  // uint32_t usrLen
299     RsExpandKernelDriverInfoPfxTy =
300         llvm::StructType::create(RsExpandKernelDriverInfoPfxTypes, "RsExpandKernelDriverInfoPfx");
301 
302     // Create the function type for expanded kernels.
303     llvm::Type *VoidTy = llvm::Type::getVoidTy(*Context);
304 
305     llvm::Type *RsExpandKernelDriverInfoPfxPtrTy = RsExpandKernelDriverInfoPfxTy->getPointerTo();
306     // void (const RsExpandKernelDriverInfoPfxTy *p, uint32_t x1, uint32_t x2, uint32_t outstep)
307     ExpandedForEachType = llvm::FunctionType::get(VoidTy,
308         {RsExpandKernelDriverInfoPfxPtrTy, Int32Ty, Int32Ty, Int32Ty}, false);
309   }
310 
311   /// @brief Create skeleton of the expanded foreach kernel.
312   ///
313   /// This creates a function with the following signature:
314   ///
315   ///   void (const RsForEachStubParamStruct *p, uint32_t x1, uint32_t x2,
316   ///         uint32_t outstep)
317   ///
createEmptyExpandedForEachKernel(llvm::StringRef OldName)318   llvm::Function *createEmptyExpandedForEachKernel(llvm::StringRef OldName) {
319     llvm::Function *ExpandedFunction =
320       llvm::Function::Create(ExpandedForEachType,
321                              llvm::GlobalValue::ExternalLinkage,
322                              OldName + ".expand", Module);
323     bccAssert(ExpandedFunction->arg_size() == kNumExpandedForeachParams);
324     llvm::Function::arg_iterator AI = ExpandedFunction->arg_begin();
325     (AI++)->setName("p");
326     (AI++)->setName("x1");
327     (AI++)->setName("x2");
328     (AI++)->setName("arg_outstep");
329     llvm::BasicBlock *Begin = llvm::BasicBlock::Create(*Context, "Begin",
330                                                        ExpandedFunction);
331     llvm::IRBuilder<> Builder(Begin);
332     Builder.CreateRetVoid();
333     return ExpandedFunction;
334   }
335 
336   // Create skeleton of a general reduce kernel's expanded accumulator.
337   //
338   // This creates a function with the following signature:
339   //
340   //  void @func.expand(%RsExpandKernelDriverInfoPfx* nocapture %p,
341   //                    i32 %x1, i32 %x2, accumType* nocapture %accum)
342   //
createEmptyExpandedReduceAccumulator(llvm::StringRef OldName,llvm::Type * AccumArgTy)343   llvm::Function *createEmptyExpandedReduceAccumulator(llvm::StringRef OldName,
344                                                        llvm::Type *AccumArgTy) {
345     llvm::Type *Int32Ty = llvm::Type::getInt32Ty(*Context);
346     llvm::Type *VoidTy = llvm::Type::getVoidTy(*Context);
347     llvm::FunctionType *ExpandedReduceAccumulatorType =
348         llvm::FunctionType::get(VoidTy,
349                                 {RsExpandKernelDriverInfoPfxTy->getPointerTo(),
350                                  Int32Ty, Int32Ty, AccumArgTy}, false);
351     llvm::Function *FnExpandedAccumulator =
352       llvm::Function::Create(ExpandedReduceAccumulatorType,
353                              llvm::GlobalValue::ExternalLinkage,
354                              OldName + ".expand", Module);
355     bccAssert(FnExpandedAccumulator->arg_size() == kNumExpandedReduceAccumulatorParams);
356 
357     llvm::Function::arg_iterator AI = FnExpandedAccumulator->arg_begin();
358 
359     using llvm::Attribute;
360 
361     llvm::Argument *Arg_p = &(*AI++);
362     Arg_p->setName("p");
363     Arg_p->addAttr(llvm::AttributeSet::get(*Context, Arg_p->getArgNo() + 1,
364                                            llvm::makeArrayRef(Attribute::NoCapture)));
365 
366     llvm::Argument *Arg_x1 = &(*AI++);
367     Arg_x1->setName("x1");
368 
369     llvm::Argument *Arg_x2 = &(*AI++);
370     Arg_x2->setName("x2");
371 
372     llvm::Argument *Arg_accum = &(*AI++);
373     Arg_accum->setName("accum");
374     Arg_accum->addAttr(llvm::AttributeSet::get(*Context, Arg_accum->getArgNo() + 1,
375                                                llvm::makeArrayRef(Attribute::NoCapture)));
376 
377     llvm::BasicBlock *Begin = llvm::BasicBlock::Create(*Context, "Begin",
378                                                        FnExpandedAccumulator);
379     llvm::IRBuilder<> Builder(Begin);
380     Builder.CreateRetVoid();
381 
382     return FnExpandedAccumulator;
383   }
384 
385   /// @brief Create an empty loop
386   ///
387   /// Create a loop of the form:
388   ///
389   /// for (i = LowerBound; i < UpperBound; i++)
390   ///   ;
391   ///
392   /// After the loop has been created, the builder is set such that
393   /// instructions can be added to the loop body.
394   ///
395   /// @param Builder The builder to use to build this loop. The current
396   ///                position of the builder is the position the loop
397   ///                will be inserted.
398   /// @param LowerBound The first value of the loop iterator
399   /// @param UpperBound The maximal value of the loop iterator
400   /// @param LoopIV A reference that will be set to the loop iterator.
401   /// @return The BasicBlock that will be executed after the loop.
createLoop(llvm::IRBuilder<> & Builder,llvm::Value * LowerBound,llvm::Value * UpperBound,llvm::Value ** LoopIV)402   llvm::BasicBlock *createLoop(llvm::IRBuilder<> &Builder,
403                                llvm::Value *LowerBound,
404                                llvm::Value *UpperBound,
405                                llvm::Value **LoopIV) {
406     bccAssert(LowerBound->getType() == UpperBound->getType());
407 
408     llvm::BasicBlock *CondBB, *AfterBB, *HeaderBB;
409     llvm::Value *Cond, *IVNext, *IV, *IVVar;
410 
411     CondBB = Builder.GetInsertBlock();
412     AfterBB = llvm::SplitBlock(CondBB, &*Builder.GetInsertPoint(), nullptr, nullptr);
413     HeaderBB = llvm::BasicBlock::Create(*Context, "Loop", CondBB->getParent());
414 
415     CondBB->getTerminator()->eraseFromParent();
416     Builder.SetInsertPoint(CondBB);
417 
418     // decltype(LowerBound) *ivvar = alloca(sizeof(int))
419     // *ivvar = LowerBound
420     IVVar = Builder.CreateAlloca(LowerBound->getType(), nullptr, BCC_INDEX_VAR_NAME);
421     Builder.CreateStore(LowerBound, IVVar);
422 
423     // if (LowerBound < Upperbound)
424     //   goto LoopHeader
425     // else
426     //   goto AfterBB
427     Cond = Builder.CreateICmpULT(LowerBound, UpperBound);
428     Builder.CreateCondBr(Cond, HeaderBB, AfterBB);
429 
430     // LoopHeader:
431     //   iv = *ivvar
432     //   <insertion point here>
433     //   iv.next = iv + 1
434     //   *ivvar = iv.next
435     //   if (iv.next < Upperbound)
436     //     goto LoopHeader
437     //   else
438     //     goto AfterBB
439     // AfterBB:
440     Builder.SetInsertPoint(HeaderBB);
441     IV = Builder.CreateLoad(IVVar, "X");
442     IVNext = Builder.CreateNUWAdd(IV, Builder.getInt32(1));
443     Builder.CreateStore(IVNext, IVVar);
444     Cond = Builder.CreateICmpULT(IVNext, UpperBound);
445     Builder.CreateCondBr(Cond, HeaderBB, AfterBB);
446     AfterBB->setName("Exit");
447     Builder.SetInsertPoint(llvm::cast<llvm::Instruction>(IVNext));
448 
449     // Record information about this loop.
450     *LoopIV = IV;
451     return AfterBB;
452   }
453 
454   // Finish building the outgoing argument list for calling a ForEach-able function.
455   //
456   // ArgVector - on input, the non-special arguments
457   //             on output, the non-special arguments combined with the special arguments
458   //               from SpecialArgVector
459   // SpecialArgVector - special arguments (from ExpandSpecialArguments())
460   // SpecialArgContextIdx - return value of ExpandSpecialArguments()
461   //                          (position of context argument in SpecialArgVector)
462   // CalleeFunction - the ForEach-able function being called
463   // Builder - for inserting code into the caller function
464   template<unsigned int ArgVectorLen, unsigned int SpecialArgVectorLen>
finishArgList(llvm::SmallVector<llvm::Value *,ArgVectorLen> & ArgVector,const llvm::SmallVector<llvm::Value *,SpecialArgVectorLen> & SpecialArgVector,const int SpecialArgContextIdx,const llvm::Function & CalleeFunction,llvm::IRBuilder<> & CallerBuilder)465   void finishArgList(      llvm::SmallVector<llvm::Value *, ArgVectorLen>        &ArgVector,
466                      const llvm::SmallVector<llvm::Value *, SpecialArgVectorLen> &SpecialArgVector,
467                      const int SpecialArgContextIdx,
468                      const llvm::Function &CalleeFunction,
469                      llvm::IRBuilder<> &CallerBuilder) {
470     /* The context argument (if any) is a pointer to an opaque user-visible type that differs from
471      * the RsExpandKernelDriverInfoPfx type used in the function we are generating (although the
472      * two types represent the same thing).  Therefore, we must introduce a pointer cast when
473      * generating a call to the kernel function.
474      */
475     const int ArgContextIdx =
476         SpecialArgContextIdx >= 0 ? (ArgVector.size() + SpecialArgContextIdx) : SpecialArgContextIdx;
477     ArgVector.append(SpecialArgVector.begin(), SpecialArgVector.end());
478     if (ArgContextIdx >= 0) {
479       llvm::Type *ContextArgType = nullptr;
480       int ArgIdx = ArgContextIdx;
481       for (const auto &Arg : CalleeFunction.getArgumentList()) {
482         if (!ArgIdx--) {
483           ContextArgType = Arg.getType();
484           break;
485         }
486       }
487       bccAssert(ContextArgType);
488       ArgVector[ArgContextIdx] = CallerBuilder.CreatePointerCast(ArgVector[ArgContextIdx], ContextArgType);
489     }
490   }
491 
492   // GEPHelper() returns a SmallVector of values suitable for passing
493   // to IRBuilder::CreateGEP(), and SmallGEPIndices is a typedef for
494   // the returned data type. It is sized so that the SmallVector
495   // returned by GEPHelper() never needs to do a heap allocation for
496   // any list of GEP indices it encounters in the code.
497   typedef llvm::SmallVector<llvm::Value *, 3> SmallGEPIndices;
498 
499   // Helper for turning a list of constant integer GEP indices into a
500   // SmallVector of llvm::Value*. The return value is suitable for
501   // passing to a GetElementPtrInst constructor or IRBuilder::CreateGEP().
502   //
503   // Inputs:
504   //   I32Args should be integers which represent the index arguments
505   //   to a GEP instruction.
506   //
507   // Returns:
508   //   Returns a SmallVector of ConstantInts.
GEPHelper(const std::initializer_list<int32_t> I32Args)509   SmallGEPIndices GEPHelper(const std::initializer_list<int32_t> I32Args) {
510     SmallGEPIndices Out(I32Args.size());
511     llvm::IntegerType *I32Ty = llvm::Type::getInt32Ty(*Context);
512     std::transform(I32Args.begin(), I32Args.end(), Out.begin(),
513                    [I32Ty](int32_t Arg) { return llvm::ConstantInt::get(I32Ty, Arg); });
514     return Out;
515   }
516 
517 public:
RSKernelExpandPass(bool pEnableStepOpt=true)518   RSKernelExpandPass(bool pEnableStepOpt = true)
519       : ModulePass(ID), Module(nullptr), Context(nullptr),
520         mEnableStepOpt(pEnableStepOpt) {
521 
522   }
523 
getAnalysisUsage(llvm::AnalysisUsage & AU) const524   virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
525     // This pass does not use any other analysis passes, but it does
526     // add/wrap the existing functions in the module (thus altering the CFG).
527   }
528 
529   // Build contribution to outgoing argument list for calling a
530   // ForEach-able function or a general reduction accumulator
531   // function, based on the special parameters of that function.
532   //
533   // Signature - metadata bits for the signature of the callee
534   // X, Arg_p - values derived directly from expanded function,
535   //            suitable for computing arguments for the callee
536   // CalleeArgs - contribution is accumulated here
537   // Bump - invoked once for each contributed outgoing argument
538   // LoopHeaderInsertionPoint - an Instruction in the loop header, before which
539   //                            this function can insert loop-invariant loads
540   //
541   // Return value is the (zero-based) position of the context (Arg_p)
542   // argument in the CalleeArgs vector, or a negative value if the
543   // context argument is not placed in the CalleeArgs vector.
ExpandSpecialArguments(uint32_t Signature,llvm::Value * X,llvm::Value * Arg_p,llvm::IRBuilder<> & Builder,llvm::SmallVector<llvm::Value *,8> & CalleeArgs,std::function<void ()> Bump,llvm::Instruction * LoopHeaderInsertionPoint)544   int ExpandSpecialArguments(uint32_t Signature,
545                              llvm::Value *X,
546                              llvm::Value *Arg_p,
547                              llvm::IRBuilder<> &Builder,
548                              llvm::SmallVector<llvm::Value*, 8> &CalleeArgs,
549                              std::function<void ()> Bump,
550                              llvm::Instruction *LoopHeaderInsertionPoint) {
551 
552     bccAssert(CalleeArgs.empty());
553 
554     int Return = -1;
555     if (bcinfo::MetadataExtractor::hasForEachSignatureCtxt(Signature)) {
556       CalleeArgs.push_back(Arg_p);
557       Bump();
558       Return = CalleeArgs.size() - 1;
559     }
560 
561     if (bcinfo::MetadataExtractor::hasForEachSignatureX(Signature)) {
562       CalleeArgs.push_back(X);
563       Bump();
564     }
565 
566     if (bcinfo::MetadataExtractor::hasForEachSignatureY(Signature) ||
567         bcinfo::MetadataExtractor::hasForEachSignatureZ(Signature)) {
568       bccAssert(LoopHeaderInsertionPoint);
569 
570       // Y and Z are loop invariant, so they can be hoisted out of the
571       // loop. Set the IRBuilder insertion point to the loop header.
572       auto OldInsertionPoint = Builder.saveIP();
573       Builder.SetInsertPoint(LoopHeaderInsertionPoint);
574 
575       if (bcinfo::MetadataExtractor::hasForEachSignatureY(Signature)) {
576         SmallGEPIndices YValueGEP(GEPHelper({0, RsExpandKernelDriverInfoPfxFieldCurrent,
577           RsLaunchDimensionsFieldY}));
578         llvm::Value *YAddr = Builder.CreateInBoundsGEP(Arg_p, YValueGEP, "Y.gep");
579         CalleeArgs.push_back(Builder.CreateLoad(YAddr, "Y"));
580         Bump();
581       }
582 
583       if (bcinfo::MetadataExtractor::hasForEachSignatureZ(Signature)) {
584         SmallGEPIndices ZValueGEP(GEPHelper({0, RsExpandKernelDriverInfoPfxFieldCurrent,
585           RsLaunchDimensionsFieldZ}));
586         llvm::Value *ZAddr = Builder.CreateInBoundsGEP(Arg_p, ZValueGEP, "Z.gep");
587         CalleeArgs.push_back(Builder.CreateLoad(ZAddr, "Z"));
588         Bump();
589       }
590 
591       Builder.restoreIP(OldInsertionPoint);
592     }
593 
594     return Return;
595   }
596 
597   // Generate loop-invariant input processing setup code for an expanded
598   // ForEach-able function or an expanded general reduction accumulator
599   // function.
600   //
601   // LoopHeader - block at the end of which the setup code will be inserted
602   // Arg_p - RSKernelDriverInfo pointer passed to the expanded function
603   // TBAAPointer - metadata for marking loads of pointer values out of RSKernelDriverInfo
604   // ArgIter - iterator pointing to first input of the UNexpanded function
605   // NumInputs - number of inputs (NOT number of ARGUMENTS)
606   //
607   // InTypes[] - this function saves input type, they will be used in ExpandInputsBody().
608   // InBufPtrs[] - this function sets each array element to point to the first cell / byte
609   //               (byte for x86, cell for other platforms) of the corresponding input allocation
610   // InStructTempSlots[] - this function sets each array element either to nullptr
611   //                       or to the result of an alloca (for the case where the
612   //                       calling convention dictates that a value must be passed
613   //                       by reference, and so we need a stacked temporary to hold
614   //                       a copy of that value)
ExpandInputsLoopInvariant(llvm::IRBuilder<> & Builder,llvm::BasicBlock * LoopHeader,llvm::Value * Arg_p,llvm::MDNode * TBAAPointer,llvm::Function::arg_iterator ArgIter,const size_t NumInputs,llvm::SmallVectorImpl<llvm::Type * > & InTypes,llvm::SmallVectorImpl<llvm::Value * > & InBufPtrs,llvm::SmallVectorImpl<llvm::Value * > & InStructTempSlots)615   void ExpandInputsLoopInvariant(llvm::IRBuilder<> &Builder, llvm::BasicBlock *LoopHeader,
616                                  llvm::Value *Arg_p,
617                                  llvm::MDNode *TBAAPointer,
618                                  llvm::Function::arg_iterator ArgIter,
619                                  const size_t NumInputs,
620                                  llvm::SmallVectorImpl<llvm::Type *> &InTypes,
621                                  llvm::SmallVectorImpl<llvm::Value *> &InBufPtrs,
622                                  llvm::SmallVectorImpl<llvm::Value *> &InStructTempSlots) {
623     bccAssert(NumInputs <= RS_KERNEL_INPUT_LIMIT);
624 
625     // Extract information about input slots. The work done
626     // here is loop-invariant, so we can hoist the operations out of the loop.
627     auto OldInsertionPoint = Builder.saveIP();
628     Builder.SetInsertPoint(LoopHeader->getTerminator());
629 
630     for (size_t InputIndex = 0; InputIndex < NumInputs; ++InputIndex, ArgIter++) {
631       llvm::Type *InType = ArgIter->getType();
632 
633       /*
634        * AArch64 calling conventions dictate that structs of sufficient size
635        * get passed by pointer instead of passed by value.  This, combined
636        * with the fact that we don't allow kernels to operate on pointer
637        * data means that if we see a kernel with a pointer parameter we know
638        * that it is a struct input that has been promoted.  As such we don't
639        * need to convert its type to a pointer.  Later we will need to know
640        * to create a temporary copy on the stack, so we save this information
641        * in InStructTempSlots.
642        */
643       if (auto PtrType = llvm::dyn_cast<llvm::PointerType>(InType)) {
644         llvm::Type *ElementType = PtrType->getElementType();
645         InStructTempSlots.push_back(Builder.CreateAlloca(ElementType, nullptr,
646                                                          "input_struct_slot"));
647       } else {
648         InType = InType->getPointerTo();
649         InStructTempSlots.push_back(nullptr);
650       }
651 
652       SmallGEPIndices InBufPtrGEP(GEPHelper({0, RsExpandKernelDriverInfoPfxFieldInPtr,
653                                              static_cast<int32_t>(InputIndex)}));
654       llvm::Value    *InBufPtrAddr = Builder.CreateInBoundsGEP(Arg_p, InBufPtrGEP, "input_buf.gep");
655       llvm::LoadInst *InBufPtr = Builder.CreateLoad(InBufPtrAddr, "input_buf");
656 
657       llvm::Value *CastInBufPtr = nullptr;
658       if (Module->getTargetTriple() != DEFAULT_X86_TRIPLE_STRING) {
659         CastInBufPtr = Builder.CreatePointerCast(InBufPtr, InType, "casted_in");
660       } else {
661         // The disagreement between module and x86 target machine datalayout
662         // causes mismatched input/output data offset between slang reflected
663         // code and bcc codegen for GetElementPtr. To solve this issue, skip the
664         // cast to InType and leave CastInBufPtr as an int8_t*.  The buffer is
665         // later indexed with an explicit byte offset computed based on
666         // X86_CUSTOM_DL_STRING and then bitcast it to actual input type.
667         CastInBufPtr = InBufPtr;
668       }
669 
670       if (gEnableRsTbaa) {
671         InBufPtr->setMetadata("tbaa", TBAAPointer);
672       }
673 
674       InTypes.push_back(InType);
675       InBufPtrs.push_back(CastInBufPtr);
676     }
677 
678     Builder.restoreIP(OldInsertionPoint);
679   }
680 
681   // Generate loop-varying input processing code for an expanded ForEach-able function
682   // or an expanded general reduction accumulator function.  Also, for the call to the
683   // UNexpanded function, collect the portion of the argument list corresponding to the
684   // inputs.
685   //
686   // Arg_x1 - first X coordinate to be processed by the expanded function
687   // TBAAAllocation - metadata for marking loads of input values out of allocations
688   // NumInputs -- number of inputs (NOT number of ARGUMENTS)
689   // InTypes[] - this function uses the saved input types in ExpandInputsLoopInvariant()
690   //             to convert the pointer of byte InPtr to its real type.
691   // InBufPtrs[] - this function consumes the information produced by ExpandInputsLoopInvariant()
692   // InStructTempSlots[] - this function consumes the information produced by ExpandInputsLoopInvariant()
693   // IndVar - value of loop induction variable (X coordinate) for a given loop iteration
694   //
695   // RootArgs - this function sets this to the list of outgoing argument values corresponding
696   //            to the inputs
ExpandInputsBody(llvm::IRBuilder<> & Builder,llvm::Value * Arg_x1,llvm::MDNode * TBAAAllocation,const size_t NumInputs,const llvm::SmallVectorImpl<llvm::Type * > & InTypes,const llvm::SmallVectorImpl<llvm::Value * > & InBufPtrs,const llvm::SmallVectorImpl<llvm::Value * > & InStructTempSlots,llvm::Value * IndVar,llvm::SmallVectorImpl<llvm::Value * > & RootArgs)697   void ExpandInputsBody(llvm::IRBuilder<> &Builder,
698                         llvm::Value *Arg_x1,
699                         llvm::MDNode *TBAAAllocation,
700                         const size_t NumInputs,
701                         const llvm::SmallVectorImpl<llvm::Type *> &InTypes,
702                         const llvm::SmallVectorImpl<llvm::Value *> &InBufPtrs,
703                         const llvm::SmallVectorImpl<llvm::Value *> &InStructTempSlots,
704                         llvm::Value *IndVar,
705                         llvm::SmallVectorImpl<llvm::Value *> &RootArgs) {
706     llvm::Value *Offset = Builder.CreateSub(IndVar, Arg_x1);
707     llvm::Type *Int32Ty = llvm::Type::getInt32Ty(*Context);
708 
709     for (size_t Index = 0; Index < NumInputs; ++Index) {
710 
711       llvm::Value *InPtr = nullptr;
712       if (Module->getTargetTriple() != DEFAULT_X86_TRIPLE_STRING) {
713         InPtr = Builder.CreateInBoundsGEP(InBufPtrs[Index], Offset);
714       } else {
715         // Treat x86 input buffer as byte[], get indexed pointer with explicit
716         // byte offset computed using a datalayout based on
717         // X86_CUSTOM_DL_STRING, then bitcast it to actual input type.
718         llvm::DataLayout DL(X86_CUSTOM_DL_STRING);
719         llvm::Type *InTy = InTypes[Index];
720         uint64_t InStep = DL.getTypeAllocSize(InTy->getPointerElementType());
721         llvm::Value *OffsetInBytes = Builder.CreateMul(Offset, llvm::ConstantInt::get(Int32Ty, InStep));
722         InPtr = Builder.CreateInBoundsGEP(InBufPtrs[Index], OffsetInBytes);
723         InPtr = Builder.CreatePointerCast(InPtr, InTy);
724       }
725 
726       llvm::Value *Input;
727       llvm::LoadInst *InputLoad = Builder.CreateLoad(InPtr, "input");
728 
729       if (gEnableRsTbaa) {
730         InputLoad->setMetadata("tbaa", TBAAAllocation);
731       }
732 
733       if (llvm::Value *TemporarySlot = InStructTempSlots[Index]) {
734         // Pass a pointer to a temporary on the stack, rather than
735         // passing a pointer to the original value. We do not want
736         // the kernel to potentially modify the input data.
737 
738         // Note: don't annotate with TBAA, since the kernel might
739         // have its own TBAA annotations for the pointer argument.
740         Builder.CreateStore(InputLoad, TemporarySlot);
741         Input = TemporarySlot;
742       } else {
743         Input = InputLoad;
744       }
745 
746       RootArgs.push_back(Input);
747     }
748   }
749 
750   /* Performs the actual optimization on a selected function. On success, the
751    * Module will contain a new function of the name "<NAME>.expand" that
752    * invokes <NAME>() in a loop with the appropriate parameters.
753    */
ExpandOldStyleForEach(llvm::Function * Function,uint32_t Signature)754   bool ExpandOldStyleForEach(llvm::Function *Function, uint32_t Signature) {
755     ALOGV("Expanding ForEach-able Function %s",
756           Function->getName().str().c_str());
757 
758     if (!Signature) {
759       Signature = getRootSignature(Function);
760       if (!Signature) {
761         // We couldn't determine how to expand this function based on its
762         // function signature.
763         return false;
764       }
765     }
766 
767     llvm::DataLayout DL(Module);
768     if (Module->getTargetTriple() == DEFAULT_X86_TRIPLE_STRING) {
769       DL.reset(X86_CUSTOM_DL_STRING);
770     }
771 
772     llvm::Function *ExpandedFunction =
773       createEmptyExpandedForEachKernel(Function->getName());
774 
775     /*
776      * Extract the expanded function's parameters.  It is guaranteed by
777      * createEmptyExpandedForEachKernel that there will be four parameters.
778      */
779 
780     bccAssert(ExpandedFunction->arg_size() == kNumExpandedForeachParams);
781 
782     llvm::Function::arg_iterator ExpandedFunctionArgIter =
783       ExpandedFunction->arg_begin();
784 
785     llvm::Value *Arg_p       = &*(ExpandedFunctionArgIter++);
786     llvm::Value *Arg_x1      = &*(ExpandedFunctionArgIter++);
787     llvm::Value *Arg_x2      = &*(ExpandedFunctionArgIter++);
788     llvm::Value *Arg_outstep = &*(ExpandedFunctionArgIter);
789 
790     llvm::Value *InStep  = nullptr;
791     llvm::Value *OutStep = nullptr;
792 
793     // Construct the actual function body.
794     llvm::IRBuilder<> Builder(&*ExpandedFunction->getEntryBlock().begin());
795 
796     // Collect and construct the arguments for the kernel().
797     // Note that we load any loop-invariant arguments before entering the Loop.
798     llvm::Function::arg_iterator FunctionArgIter = Function->arg_begin();
799 
800     llvm::Type  *InTy      = nullptr;
801     llvm::Value *InBufPtr = nullptr;
802     if (bcinfo::MetadataExtractor::hasForEachSignatureIn(Signature)) {
803       SmallGEPIndices InStepGEP(GEPHelper({0, RsExpandKernelDriverInfoPfxFieldInStride, 0}));
804       llvm::LoadInst *InStepArg  = Builder.CreateLoad(
805         Builder.CreateInBoundsGEP(Arg_p, InStepGEP, "instep_addr.gep"), "instep_addr");
806 
807       InTy = (FunctionArgIter++)->getType();
808       InStep = getStepValue(&DL, InTy, InStepArg);
809 
810       InStep->setName("instep");
811 
812       SmallGEPIndices InputAddrGEP(GEPHelper({0, RsExpandKernelDriverInfoPfxFieldInPtr, 0}));
813       InBufPtr = Builder.CreateLoad(
814         Builder.CreateInBoundsGEP(Arg_p, InputAddrGEP, "input_buf.gep"), "input_buf");
815     }
816 
817     llvm::Type *OutTy = nullptr;
818     llvm::Value *OutBasePtr = nullptr;
819     if (bcinfo::MetadataExtractor::hasForEachSignatureOut(Signature)) {
820       OutTy = (FunctionArgIter++)->getType();
821       OutStep = getStepValue(&DL, OutTy, Arg_outstep);
822       OutStep->setName("outstep");
823       SmallGEPIndices OutBaseGEP(GEPHelper({0, RsExpandKernelDriverInfoPfxFieldOutPtr, 0}));
824       OutBasePtr = Builder.CreateLoad(Builder.CreateInBoundsGEP(Arg_p, OutBaseGEP, "out_buf.gep"));
825     }
826 
827     llvm::Value *UsrData = nullptr;
828     if (bcinfo::MetadataExtractor::hasForEachSignatureUsrData(Signature)) {
829       llvm::Type *UsrDataTy = (FunctionArgIter++)->getType();
830       llvm::Value *UsrDataPointerAddr = Builder.CreateStructGEP(nullptr, Arg_p, RsExpandKernelDriverInfoPfxFieldUsr);
831       UsrData = Builder.CreatePointerCast(Builder.CreateLoad(UsrDataPointerAddr), UsrDataTy);
832       UsrData->setName("UsrData");
833     }
834 
835     llvm::BasicBlock *LoopHeader = Builder.GetInsertBlock();
836     llvm::Value *IV;
837     createLoop(Builder, Arg_x1, Arg_x2, &IV);
838 
839     llvm::SmallVector<llvm::Value*, 8> CalleeArgs;
840     const int CalleeArgsContextIdx = ExpandSpecialArguments(Signature, IV, Arg_p, Builder, CalleeArgs,
841                                                             [&FunctionArgIter]() { FunctionArgIter++; },
842                                                             LoopHeader->getTerminator());
843 
844     bccAssert(FunctionArgIter == Function->arg_end());
845 
846     // Populate the actual call to kernel().
847     llvm::SmallVector<llvm::Value*, 8> RootArgs;
848 
849     llvm::Value *InPtr  = nullptr;
850     llvm::Value *OutPtr = nullptr;
851 
852     // Calculate the current input and output pointers
853     //
854     // We always calculate the input/output pointers with a GEP operating on i8
855     // values and only cast at the very end to OutTy. This is because the step
856     // between two values is given in bytes.
857     //
858     // TODO: We could further optimize the output by using a GEP operation of
859     // type 'OutTy' in cases where the element type of the allocation allows.
860     if (OutBasePtr) {
861       llvm::Value *OutOffset = Builder.CreateSub(IV, Arg_x1);
862       OutOffset = Builder.CreateMul(OutOffset, OutStep);
863       OutPtr = Builder.CreateInBoundsGEP(OutBasePtr, OutOffset);
864       OutPtr = Builder.CreatePointerCast(OutPtr, OutTy);
865     }
866 
867     if (InBufPtr) {
868       llvm::Value *InOffset = Builder.CreateSub(IV, Arg_x1);
869       InOffset = Builder.CreateMul(InOffset, InStep);
870       InPtr = Builder.CreateInBoundsGEP(InBufPtr, InOffset);
871       InPtr = Builder.CreatePointerCast(InPtr, InTy);
872     }
873 
874     if (InPtr) {
875       RootArgs.push_back(InPtr);
876     }
877 
878     if (OutPtr) {
879       RootArgs.push_back(OutPtr);
880     }
881 
882     if (UsrData) {
883       RootArgs.push_back(UsrData);
884     }
885 
886     finishArgList(RootArgs, CalleeArgs, CalleeArgsContextIdx, *Function, Builder);
887 
888     Builder.CreateCall(Function, RootArgs);
889 
890     return true;
891   }
892 
893   /* Expand a pass-by-value foreach kernel.
894    */
ExpandForEach(llvm::Function * Function,uint32_t Signature)895   bool ExpandForEach(llvm::Function *Function, uint32_t Signature) {
896     bccAssert(bcinfo::MetadataExtractor::hasForEachSignatureKernel(Signature));
897     ALOGV("Expanding kernel Function %s", Function->getName().str().c_str());
898 
899     // TODO: Refactor this to share functionality with ExpandOldStyleForEach.
900     llvm::DataLayout DL(Module);
901     if (Module->getTargetTriple() == DEFAULT_X86_TRIPLE_STRING) {
902       DL.reset(X86_CUSTOM_DL_STRING);
903     }
904     llvm::Type *Int32Ty = llvm::Type::getInt32Ty(*Context);
905 
906     llvm::Function *ExpandedFunction =
907       createEmptyExpandedForEachKernel(Function->getName());
908 
909     /*
910      * Extract the expanded function's parameters.  It is guaranteed by
911      * createEmptyExpandedForEachKernel that there will be four parameters.
912      */
913 
914     bccAssert(ExpandedFunction->arg_size() == kNumExpandedForeachParams);
915 
916     llvm::Function::arg_iterator ExpandedFunctionArgIter =
917       ExpandedFunction->arg_begin();
918 
919     llvm::Value *Arg_p       = &*(ExpandedFunctionArgIter++);
920     llvm::Value *Arg_x1      = &*(ExpandedFunctionArgIter++);
921     llvm::Value *Arg_x2      = &*(ExpandedFunctionArgIter++);
922     // Arg_outstep is not used by expanded new-style forEach kernels.
923 
924     // Construct the actual function body.
925     llvm::IRBuilder<> Builder(&*ExpandedFunction->getEntryBlock().begin());
926 
927     // Create TBAA meta-data.
928     llvm::MDNode *TBAARenderScriptDistinct, *TBAARenderScript,
929                  *TBAAAllocation, *TBAAPointer;
930     llvm::MDBuilder MDHelper(*Context);
931 
932     TBAARenderScriptDistinct =
933       MDHelper.createTBAARoot(kRenderScriptTBAARootName);
934     TBAARenderScript = MDHelper.createTBAANode(kRenderScriptTBAANodeName,
935         TBAARenderScriptDistinct);
936     TBAAAllocation = MDHelper.createTBAAScalarTypeNode("allocation",
937                                                        TBAARenderScript);
938     TBAAAllocation = MDHelper.createTBAAStructTagNode(TBAAAllocation,
939                                                       TBAAAllocation, 0);
940     TBAAPointer = MDHelper.createTBAAScalarTypeNode("pointer",
941                                                     TBAARenderScript);
942     TBAAPointer = MDHelper.createTBAAStructTagNode(TBAAPointer, TBAAPointer, 0);
943 
944     /*
945      * Collect and construct the arguments for the kernel().
946      *
947      * Note that we load any loop-invariant arguments before entering the Loop.
948      */
949     size_t NumRemainingInputs = Function->arg_size();
950 
951     // No usrData parameter on kernels.
952     bccAssert(
953         !bcinfo::MetadataExtractor::hasForEachSignatureUsrData(Signature));
954 
955     llvm::Function::arg_iterator ArgIter = Function->arg_begin();
956 
957     // Check the return type
958     llvm::Type     *OutTy            = nullptr;
959     llvm::LoadInst *OutBasePtr       = nullptr;
960     llvm::Value    *CastedOutBasePtr = nullptr;
961 
962     bool PassOutByPointer = false;
963 
964     if (bcinfo::MetadataExtractor::hasForEachSignatureOut(Signature)) {
965       llvm::Type *OutBaseTy = Function->getReturnType();
966 
967       if (OutBaseTy->isVoidTy()) {
968         PassOutByPointer = true;
969         OutTy = ArgIter->getType();
970 
971         ArgIter++;
972         --NumRemainingInputs;
973       } else {
974         // We don't increment Args, since we are using the actual return type.
975         OutTy = OutBaseTy->getPointerTo();
976       }
977 
978       SmallGEPIndices OutBaseGEP(GEPHelper({0, RsExpandKernelDriverInfoPfxFieldOutPtr, 0}));
979       OutBasePtr = Builder.CreateLoad(Builder.CreateInBoundsGEP(Arg_p, OutBaseGEP, "out_buf.gep"));
980 
981       if (gEnableRsTbaa) {
982         OutBasePtr->setMetadata("tbaa", TBAAPointer);
983       }
984 
985       if (Module->getTargetTriple() != DEFAULT_X86_TRIPLE_STRING) {
986         CastedOutBasePtr = Builder.CreatePointerCast(OutBasePtr, OutTy, "casted_out");
987       } else {
988         // The disagreement between module and x86 target machine datalayout
989         // causes mismatched input/output data offset between slang reflected
990         // code and bcc codegen for GetElementPtr. To solve this issue, skip the
991         // cast to OutTy and leave CastedOutBasePtr as an int8_t*.  The buffer
992         // is later indexed with an explicit byte offset computed based on
993         // X86_CUSTOM_DL_STRING and then bitcast it to actual output type.
994         CastedOutBasePtr = OutBasePtr;
995       }
996     }
997 
998     llvm::SmallVector<llvm::Type*,  8> InTypes;
999     llvm::SmallVector<llvm::Value*, 8> InBufPtrs;
1000     llvm::SmallVector<llvm::Value*, 8> InStructTempSlots;
1001 
1002     bccAssert(NumRemainingInputs <= RS_KERNEL_INPUT_LIMIT);
1003 
1004     // Create the loop structure.
1005     llvm::BasicBlock *LoopHeader = Builder.GetInsertBlock();
1006     llvm::Value *IV;
1007     createLoop(Builder, Arg_x1, Arg_x2, &IV);
1008 
1009     llvm::SmallVector<llvm::Value*, 8> CalleeArgs;
1010     const int CalleeArgsContextIdx =
1011       ExpandSpecialArguments(Signature, IV, Arg_p, Builder, CalleeArgs,
1012                              [&NumRemainingInputs]() { --NumRemainingInputs; },
1013                              LoopHeader->getTerminator());
1014 
1015     // After ExpandSpecialArguments() gets called, NumRemainingInputs
1016     // counts the number of arguments to the kernel that correspond to
1017     // an array entry from the InPtr field of the DriverInfo
1018     // structure.
1019     const size_t NumInPtrArguments = NumRemainingInputs;
1020 
1021     if (NumInPtrArguments > 0) {
1022       ExpandInputsLoopInvariant(Builder, LoopHeader, Arg_p, TBAAPointer, ArgIter, NumInPtrArguments,
1023                                 InTypes, InBufPtrs, InStructTempSlots);
1024     }
1025 
1026     // Populate the actual call to kernel().
1027     llvm::SmallVector<llvm::Value*, 8> RootArgs;
1028 
1029     // Calculate the current input and output pointers.
1030 
1031     // Output
1032 
1033     llvm::Value *OutPtr = nullptr;
1034     if (CastedOutBasePtr) {
1035       llvm::Value *OutOffset = Builder.CreateSub(IV, Arg_x1);
1036 
1037       if (Module->getTargetTriple() != DEFAULT_X86_TRIPLE_STRING) {
1038         OutPtr = Builder.CreateInBoundsGEP(CastedOutBasePtr, OutOffset);
1039       } else {
1040         // Treat x86 output buffer as byte[], get indexed pointer with explicit
1041         // byte offset computed using a datalayout based on
1042         // X86_CUSTOM_DL_STRING, then bitcast it to actual output type.
1043         uint64_t OutStep = DL.getTypeAllocSize(OutTy->getPointerElementType());
1044         llvm::Value *OutOffsetInBytes = Builder.CreateMul(OutOffset, llvm::ConstantInt::get(Int32Ty, OutStep));
1045         OutPtr = Builder.CreateInBoundsGEP(CastedOutBasePtr, OutOffsetInBytes);
1046         OutPtr = Builder.CreatePointerCast(OutPtr, OutTy);
1047       }
1048 
1049       if (PassOutByPointer) {
1050         RootArgs.push_back(OutPtr);
1051       }
1052     }
1053 
1054     // Inputs
1055 
1056     if (NumInPtrArguments > 0) {
1057       ExpandInputsBody(Builder, Arg_x1, TBAAAllocation, NumInPtrArguments,
1058                        InTypes, InBufPtrs, InStructTempSlots, IV, RootArgs);
1059     }
1060 
1061     finishArgList(RootArgs, CalleeArgs, CalleeArgsContextIdx, *Function, Builder);
1062 
1063     llvm::Value *RetVal = Builder.CreateCall(Function, RootArgs);
1064 
1065     if (OutPtr && !PassOutByPointer) {
1066       RetVal->setName("call.result");
1067       llvm::StoreInst *Store = Builder.CreateStore(RetVal, OutPtr);
1068       if (gEnableRsTbaa) {
1069         Store->setMetadata("tbaa", TBAAAllocation);
1070       }
1071     }
1072 
1073     return true;
1074   }
1075 
1076   // Certain categories of functions that make up a general
1077   // reduce-style kernel are called directly from the driver with no
1078   // expansion needed.  For a function in such a category, we need to
1079   // promote linkage from static to external, to ensure that the
1080   // function is visible to the driver in the dynamic symbol table.
1081   // This promotion is safe because we don't have any kind of cross
1082   // translation unit linkage model (except for linking against
1083   // RenderScript libraries), so we do not risk name clashes.
PromoteReduceFunction(const char * Name,FunctionSet & PromotedFunctions)1084   bool PromoteReduceFunction(const char *Name, FunctionSet &PromotedFunctions) {
1085     if (!Name)  // a presumably-optional function that is not present
1086       return false;
1087 
1088     llvm::Function *Fn = Module->getFunction(Name);
1089     bccAssert(Fn != nullptr);
1090     if (PromotedFunctions.insert(Fn).second) {
1091       bccAssert(Fn->getLinkage() == llvm::GlobalValue::InternalLinkage);
1092       Fn->setLinkage(llvm::GlobalValue::ExternalLinkage);
1093       return true;
1094     }
1095 
1096     return false;
1097   }
1098 
1099   // Expand the accumulator function for a general reduce-style kernel.
1100   //
1101   // The input is a function of the form
1102   //
1103   //   define void @func(accumType* %accum, foo1 in1[, ... fooN inN] [, special arguments])
1104   //
1105   // where all arguments except the first are the same as for a foreach kernel.
1106   //
1107   // The input accumulator function gets expanded into a function of the form
1108   //
1109   //   define void @func.expand(%RsExpandKernelDriverInfoPfx* %p, i32 %x1, i32 %x2, accumType* %accum)
1110   //
1111   // which performs a serial accumulaion of elements [x1, x2) into *%accum.
1112   //
1113   // In pseudocode, @func.expand does:
1114   //
1115   //   for (i = %x1; i < %x2; ++i) {
1116   //     func(%accum,
1117   //          *((foo1 *)p->inPtr[0] + i)[, ... *((fooN *)p->inPtr[N-1] + i)
1118   //          [, p] [, i] [, p->current.y] [, p->current.z]);
1119   //   }
1120   //
1121   // This is very similar to foreach kernel expansion with no output.
ExpandReduceAccumulator(llvm::Function * FnAccumulator,uint32_t Signature,size_t NumInputs)1122   bool ExpandReduceAccumulator(llvm::Function *FnAccumulator, uint32_t Signature, size_t NumInputs) {
1123     ALOGV("Expanding accumulator %s for general reduce kernel",
1124           FnAccumulator->getName().str().c_str());
1125 
1126     // Create TBAA meta-data.
1127     llvm::MDNode *TBAARenderScriptDistinct, *TBAARenderScript,
1128                  *TBAAAllocation, *TBAAPointer;
1129     llvm::MDBuilder MDHelper(*Context);
1130     TBAARenderScriptDistinct =
1131       MDHelper.createTBAARoot(kRenderScriptTBAARootName);
1132     TBAARenderScript = MDHelper.createTBAANode(kRenderScriptTBAANodeName,
1133         TBAARenderScriptDistinct);
1134     TBAAAllocation = MDHelper.createTBAAScalarTypeNode("allocation",
1135                                                        TBAARenderScript);
1136     TBAAAllocation = MDHelper.createTBAAStructTagNode(TBAAAllocation,
1137                                                       TBAAAllocation, 0);
1138     TBAAPointer = MDHelper.createTBAAScalarTypeNode("pointer",
1139                                                     TBAARenderScript);
1140     TBAAPointer = MDHelper.createTBAAStructTagNode(TBAAPointer, TBAAPointer, 0);
1141 
1142     auto AccumulatorArgIter = FnAccumulator->arg_begin();
1143 
1144     // Create empty accumulator function.
1145     llvm::Function *FnExpandedAccumulator =
1146         createEmptyExpandedReduceAccumulator(FnAccumulator->getName(),
1147                                              (AccumulatorArgIter++)->getType());
1148 
1149     // Extract the expanded accumulator's parameters.  It is
1150     // guaranteed by createEmptyExpandedReduceAccumulator that
1151     // there will be 4 parameters.
1152     bccAssert(FnExpandedAccumulator->arg_size() == kNumExpandedReduceAccumulatorParams);
1153     auto ExpandedAccumulatorArgIter = FnExpandedAccumulator->arg_begin();
1154     llvm::Value *Arg_p     = &*(ExpandedAccumulatorArgIter++);
1155     llvm::Value *Arg_x1    = &*(ExpandedAccumulatorArgIter++);
1156     llvm::Value *Arg_x2    = &*(ExpandedAccumulatorArgIter++);
1157     llvm::Value *Arg_accum = &*(ExpandedAccumulatorArgIter++);
1158 
1159     // Construct the actual function body.
1160     llvm::IRBuilder<> Builder(&*FnExpandedAccumulator->getEntryBlock().begin());
1161 
1162     // Create the loop structure.
1163     llvm::BasicBlock *LoopHeader = Builder.GetInsertBlock();
1164     llvm::Value *IndVar;
1165     createLoop(Builder, Arg_x1, Arg_x2, &IndVar);
1166 
1167     llvm::SmallVector<llvm::Value*, 8> CalleeArgs;
1168     const int CalleeArgsContextIdx =
1169         ExpandSpecialArguments(Signature, IndVar, Arg_p, Builder, CalleeArgs,
1170                                [](){}, LoopHeader->getTerminator());
1171 
1172     llvm::SmallVector<llvm::Type*,  8> InTypes;
1173     llvm::SmallVector<llvm::Value*, 8> InBufPtrs;
1174     llvm::SmallVector<llvm::Value*, 8> InStructTempSlots;
1175     ExpandInputsLoopInvariant(Builder, LoopHeader, Arg_p, TBAAPointer, AccumulatorArgIter, NumInputs,
1176                               InTypes, InBufPtrs, InStructTempSlots);
1177 
1178     // Populate the actual call to the original accumulator.
1179     llvm::SmallVector<llvm::Value*, 8> RootArgs;
1180     RootArgs.push_back(Arg_accum);
1181     ExpandInputsBody(Builder, Arg_x1, TBAAAllocation, NumInputs, InTypes, InBufPtrs, InStructTempSlots,
1182                      IndVar, RootArgs);
1183     finishArgList(RootArgs, CalleeArgs, CalleeArgsContextIdx, *FnAccumulator, Builder);
1184     Builder.CreateCall(FnAccumulator, RootArgs);
1185 
1186     return true;
1187   }
1188 
1189   // Create a combiner function for a general reduce-style kernel that lacks one,
1190   // by calling the accumulator function.
1191   //
1192   // The accumulator function must be of the form
1193   //
1194   //   define void @accumFn(accumType* %accum, accumType %in)
1195   //
1196   // A combiner function will be generated of the form
1197   //
1198   //   define void @accumFn.combiner(accumType* %accum, accumType* %other) {
1199   //     %1 = load accumType, accumType* %other
1200   //     call void @accumFn(accumType* %accum, accumType %1);
1201   //   }
CreateReduceCombinerFromAccumulator(llvm::Function * FnAccumulator)1202   bool CreateReduceCombinerFromAccumulator(llvm::Function *FnAccumulator) {
1203     ALOGV("Creating combiner from accumulator %s for general reduce kernel",
1204           FnAccumulator->getName().str().c_str());
1205 
1206     using llvm::Attribute;
1207 
1208     bccAssert(FnAccumulator->arg_size() == 2);
1209     auto AccumulatorArgIter = FnAccumulator->arg_begin();
1210     llvm::Value *AccumulatorArg_accum = &*(AccumulatorArgIter++);
1211     llvm::Value *AccumulatorArg_in    = &*(AccumulatorArgIter++);
1212     llvm::Type *AccumulatorArgType = AccumulatorArg_accum->getType();
1213     bccAssert(AccumulatorArgType->isPointerTy());
1214 
1215     llvm::Type *VoidTy = llvm::Type::getVoidTy(*Context);
1216     llvm::FunctionType *CombinerType =
1217         llvm::FunctionType::get(VoidTy, { AccumulatorArgType, AccumulatorArgType }, false);
1218     llvm::Function *FnCombiner =
1219         llvm::Function::Create(CombinerType, llvm::GlobalValue::ExternalLinkage,
1220                                nameReduceCombinerFromAccumulator(FnAccumulator->getName()),
1221                                Module);
1222 
1223     auto CombinerArgIter = FnCombiner->arg_begin();
1224 
1225     llvm::Argument *CombinerArg_accum = &(*CombinerArgIter++);
1226     CombinerArg_accum->setName("accum");
1227     CombinerArg_accum->addAttr(llvm::AttributeSet::get(*Context, CombinerArg_accum->getArgNo() + 1,
1228                                                        llvm::makeArrayRef(Attribute::NoCapture)));
1229 
1230     llvm::Argument *CombinerArg_other = &(*CombinerArgIter++);
1231     CombinerArg_other->setName("other");
1232     CombinerArg_other->addAttr(llvm::AttributeSet::get(*Context, CombinerArg_other->getArgNo() + 1,
1233                                                        llvm::makeArrayRef(Attribute::NoCapture)));
1234 
1235     llvm::BasicBlock *BB = llvm::BasicBlock::Create(*Context, "BB", FnCombiner);
1236     llvm::IRBuilder<> Builder(BB);
1237 
1238     if (AccumulatorArg_in->getType()->isPointerTy()) {
1239       // Types of sufficient size get passed by pointer-to-copy rather
1240       // than passed by value.  An accumulator cannot take a pointer
1241       // at the user level; so if we see a pointer here, we know that
1242       // we have a pass-by-pointer-to-copy case.
1243       llvm::Type *ElementType = AccumulatorArg_in->getType()->getPointerElementType();
1244       llvm::Value *TempMem = Builder.CreateAlloca(ElementType, nullptr, "caller_copy");
1245       Builder.CreateStore(Builder.CreateLoad(CombinerArg_other), TempMem);
1246       Builder.CreateCall(FnAccumulator, { CombinerArg_accum, TempMem });
1247     } else {
1248       llvm::Value *TypeAdjustedOther = CombinerArg_other;
1249       if (AccumulatorArgType->getPointerElementType() != AccumulatorArg_in->getType()) {
1250         // Call lowering by frontend has done some type coercion
1251         TypeAdjustedOther = Builder.CreatePointerCast(CombinerArg_other,
1252                                                       AccumulatorArg_in->getType()->getPointerTo(),
1253                                                       "cast");
1254       }
1255       llvm::Value *DerefOther = Builder.CreateLoad(TypeAdjustedOther);
1256       Builder.CreateCall(FnAccumulator, { CombinerArg_accum, DerefOther });
1257     }
1258     Builder.CreateRetVoid();
1259 
1260     return true;
1261   }
1262 
1263   /// @brief Checks if pointers to allocation internals are exposed
1264   ///
1265   /// This function verifies if through the parameters passed to the kernel
1266   /// or through calls to the runtime library the script gains access to
1267   /// pointers pointing to data within a RenderScript Allocation.
1268   /// If we know we control all loads from and stores to data within
1269   /// RenderScript allocations and if we know the run-time internal accesses
1270   /// are all annotated with RenderScript TBAA metadata, only then we
1271   /// can safely use TBAA to distinguish between generic and from-allocation
1272   /// pointers.
allocPointersExposed(llvm::Module & Module)1273   bool allocPointersExposed(llvm::Module &Module) {
1274     // Old style kernel function can expose pointers to elements within
1275     // allocations.
1276     // TODO: Extend analysis to allow simple cases of old-style kernels.
1277     for (size_t i = 0; i < mExportForEachCount; ++i) {
1278       const char *Name = mExportForEachNameList[i];
1279       uint32_t Signature = mExportForEachSignatureList[i];
1280       if (Module.getFunction(Name) &&
1281           !bcinfo::MetadataExtractor::hasForEachSignatureKernel(Signature)) {
1282         return true;
1283       }
1284     }
1285 
1286     // Check for library functions that expose a pointer to an Allocation or
1287     // that are not yet annotated with RenderScript-specific tbaa information.
1288     static const std::vector<const char *> Funcs{
1289       // rsGetElementAt(...)
1290       "_Z14rsGetElementAt13rs_allocationj",
1291       "_Z14rsGetElementAt13rs_allocationjj",
1292       "_Z14rsGetElementAt13rs_allocationjjj",
1293 
1294       // rsSetElementAt()
1295       "_Z14rsSetElementAt13rs_allocationPvj",
1296       "_Z14rsSetElementAt13rs_allocationPvjj",
1297       "_Z14rsSetElementAt13rs_allocationPvjjj",
1298 
1299       // rsGetElementAtYuv_uchar_Y()
1300       "_Z25rsGetElementAtYuv_uchar_Y13rs_allocationjj",
1301 
1302       // rsGetElementAtYuv_uchar_U()
1303       "_Z25rsGetElementAtYuv_uchar_U13rs_allocationjj",
1304 
1305       // rsGetElementAtYuv_uchar_V()
1306       "_Z25rsGetElementAtYuv_uchar_V13rs_allocationjj",
1307     };
1308 
1309     for (auto FI : Funcs) {
1310       llvm::Function *Function = Module.getFunction(FI);
1311 
1312       if (!Function) {
1313         ALOGE("Missing run-time function '%s'", FI);
1314         return true;
1315       }
1316 
1317       if (Function->getNumUses() > 0) {
1318         return true;
1319       }
1320     }
1321 
1322     return false;
1323   }
1324 
1325   /// @brief Connect RenderScript TBAA metadata to C/C++ metadata
1326   ///
1327   /// The TBAA metadata used to annotate loads/stores from RenderScript
1328   /// Allocations is generated in a separate TBAA tree with a
1329   /// "RenderScript Distinct TBAA" root node. LLVM does assume may-alias for
1330   /// all nodes in unrelated alias analysis trees. This function makes the
1331   /// "RenderScript TBAA" node (which is parented by the Distinct TBAA root),
1332   /// a subtree of the normal C/C++ TBAA tree aside of normal C/C++ types. With
1333   /// the connected trees every access to an Allocation is resolved to
1334   /// must-alias if compared to a normal C/C++ access.
connectRenderScriptTBAAMetadata(llvm::Module & Module)1335   void connectRenderScriptTBAAMetadata(llvm::Module &Module) {
1336     llvm::MDBuilder MDHelper(*Context);
1337     llvm::MDNode *TBAARenderScriptDistinct =
1338       MDHelper.createTBAARoot("RenderScript Distinct TBAA");
1339     llvm::MDNode *TBAARenderScript = MDHelper.createTBAANode(
1340         "RenderScript TBAA", TBAARenderScriptDistinct);
1341     llvm::MDNode *TBAARoot     = MDHelper.createTBAARoot("Simple C/C++ TBAA");
1342     TBAARenderScript->replaceOperandWith(1, TBAARoot);
1343   }
1344 
runOnModule(llvm::Module & Module)1345   virtual bool runOnModule(llvm::Module &Module) {
1346     bool Changed  = false;
1347     this->Module  = &Module;
1348     Context = &Module.getContext();
1349 
1350     buildTypes();
1351 
1352     bcinfo::MetadataExtractor me(&Module);
1353     if (!me.extract()) {
1354       ALOGE("Could not extract metadata from module!");
1355       return false;
1356     }
1357 
1358     // Expand forEach_* style kernels.
1359     mExportForEachCount = me.getExportForEachSignatureCount();
1360     mExportForEachNameList = me.getExportForEachNameList();
1361     mExportForEachSignatureList = me.getExportForEachSignatureList();
1362 
1363     for (size_t i = 0; i < mExportForEachCount; ++i) {
1364       const char *name = mExportForEachNameList[i];
1365       uint32_t signature = mExportForEachSignatureList[i];
1366       llvm::Function *kernel = Module.getFunction(name);
1367       if (kernel) {
1368         if (bcinfo::MetadataExtractor::hasForEachSignatureKernel(signature)) {
1369           Changed |= ExpandForEach(kernel, signature);
1370           kernel->setLinkage(llvm::GlobalValue::InternalLinkage);
1371         } else if (kernel->getReturnType()->isVoidTy()) {
1372           Changed |= ExpandOldStyleForEach(kernel, signature);
1373           kernel->setLinkage(llvm::GlobalValue::InternalLinkage);
1374         } else {
1375           // There are some graphics root functions that are not
1376           // expanded, but that will be called directly. For those
1377           // functions, we can not set the linkage to internal.
1378         }
1379       }
1380     }
1381 
1382     // Process general reduce_* style functions.
1383     const size_t ExportReduceCount = me.getExportReduceCount();
1384     const bcinfo::MetadataExtractor::Reduce *ExportReduceList = me.getExportReduceList();
1385     //   Note that functions can be shared between kernels
1386     FunctionSet PromotedFunctions, ExpandedAccumulators, AccumulatorsForCombiners;
1387 
1388     for (size_t i = 0; i < ExportReduceCount; ++i) {
1389       Changed |= PromoteReduceFunction(ExportReduceList[i].mInitializerName, PromotedFunctions);
1390       Changed |= PromoteReduceFunction(ExportReduceList[i].mCombinerName, PromotedFunctions);
1391       Changed |= PromoteReduceFunction(ExportReduceList[i].mOutConverterName, PromotedFunctions);
1392 
1393       // Accumulator
1394       llvm::Function *accumulator = Module.getFunction(ExportReduceList[i].mAccumulatorName);
1395       bccAssert(accumulator != nullptr);
1396       if (ExpandedAccumulators.insert(accumulator).second)
1397         Changed |= ExpandReduceAccumulator(accumulator,
1398                                            ExportReduceList[i].mSignature,
1399                                            ExportReduceList[i].mInputCount);
1400       if (!ExportReduceList[i].mCombinerName) {
1401         if (AccumulatorsForCombiners.insert(accumulator).second)
1402           Changed |= CreateReduceCombinerFromAccumulator(accumulator);
1403       }
1404     }
1405 
1406     if (gEnableRsTbaa && !allocPointersExposed(Module)) {
1407       connectRenderScriptTBAAMetadata(Module);
1408     }
1409 
1410     return Changed;
1411   }
1412 
getPassName() const1413   virtual const char *getPassName() const {
1414     return "forEach_* and reduce_* function expansion";
1415   }
1416 
1417 }; // end RSKernelExpandPass
1418 
1419 } // end anonymous namespace
1420 
1421 char RSKernelExpandPass::ID = 0;
1422 static llvm::RegisterPass<RSKernelExpandPass> X("kernelexp", "Kernel Expand Pass");
1423 
1424 namespace bcc {
1425 
1426 const char BCC_INDEX_VAR_NAME[] = "rsIndex";
1427 
1428 llvm::ModulePass *
createRSKernelExpandPass(bool pEnableStepOpt)1429 createRSKernelExpandPass(bool pEnableStepOpt) {
1430   return new RSKernelExpandPass(pEnableStepOpt);
1431 }
1432 
1433 } // end namespace bcc
1434