19fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar/*
29fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar * Copyright 2015, The Android Open Source Project
39fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar *
49fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar * Licensed under the Apache License, Version 2.0 (the "License");
59fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar * you may not use this file except in compliance with the License.
69fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar * You may obtain a copy of the License at
79fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar *
89fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar *     http://www.apache.org/licenses/LICENSE-2.0
99fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar *
109fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar * Unless required by applicable law or agreed to in writing, software
119fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar * distributed under the License is distributed on an "AS IS" BASIS,
129fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar * See the License for the specific language governing permissions and
149fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar * limitations under the License.
159fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar */
169fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar
17a2dd52f0710c214e00c1a13e25116e1af5eec77aJean-Luc Brouillet#include "Log.h"
18a2dd52f0710c214e00c1a13e25116e1af5eec77aJean-Luc Brouillet#include "RSTransforms.h"
199fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar
209fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar#include <cstdlib>
219fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar
229fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar#include <llvm/IR/Instructions.h>
239fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar#include <llvm/IR/Metadata.h>
249fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar#include <llvm/IR/Module.h>
259fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar#include <llvm/IR/Function.h>
269fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar#include <llvm/Pass.h>
279fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar
289fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainarnamespace { // anonymous namespace
299fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar
309fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar// Create a Module pass that screens all the global functions in the module and
319fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar// check if any non-threadable function is callable.  If so, we mark the
329fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar// Module as non-threadable by adding a metadata flag '#rs_is_threadable'
339fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar
349fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainarclass RSIsThreadablePass : public llvm::ModulePass {
359fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainarprivate:
369fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar  static char ID;
379fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar
389fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar  std::vector<std::string> nonThreadableFns = {
399fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z22rsgBindProgramFragment19rs_program_fragment",
409fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z19rsgBindProgramStore16rs_program_store",
419fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z20rsgBindProgramVertex17rs_program_vertex",
429fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z20rsgBindProgramRaster17rs_program_raster",
439fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z14rsgBindSampler19rs_program_fragmentj10rs_sampler",
449fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z14rsgBindTexture19rs_program_fragmentj13rs_allocation",
459fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z15rsgBindConstant19rs_program_fragmentj13rs_allocation",
469fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z15rsgBindConstant17rs_program_vertexj13rs_allocation",
479fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z36rsgProgramVertexLoadProjectionMatrixPK12rs_matrix4x4",
489fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z31rsgProgramVertexLoadModelMatrixPK12rs_matrix4x4",
499fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z33rsgProgramVertexLoadTextureMatrixPK12rs_matrix4x4",
509fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z35rsgProgramVertexGetProjectionMatrixP12rs_matrix4x4",
519fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z31rsgProgramFragmentConstantColor19rs_program_fragmentffff",
529fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z11rsgGetWidthv",
539fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z12rsgGetHeightv",
549fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z11rsgDrawRectfffff",
559fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z11rsgDrawQuadffffffffffff",
569fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z20rsgDrawQuadTexCoordsffffffffffffffffffff",
579fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z24rsgDrawSpriteScreenspacefffff",
589fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z11rsgDrawMesh7rs_mesh",
599fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z11rsgDrawMesh7rs_meshj",
609fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z11rsgDrawMesh7rs_meshjjj",
619fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z25rsgMeshComputeBoundingBox7rs_meshPfS0_S0_S0_S0_S0_",
629fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z11rsgDrawPath7rs_path",
639fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z13rsgClearColorffff",
649fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z13rsgClearDepthf",
659fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z11rsgDrawTextPKcii",
669fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z11rsgDrawText13rs_allocationii",
679fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z14rsgMeasureTextPKcPiS1_S1_S1_",
689fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z14rsgMeasureText13rs_allocationPiS0_S0_S0_",
699fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z11rsgBindFont7rs_font",
709fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z12rsgFontColorffff",
719fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z18rsgBindColorTarget13rs_allocationj",
729fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z18rsgBindDepthTarget13rs_allocation",
739fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z19rsgClearColorTargetj",
749fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z19rsgClearDepthTargetv",
759fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z24rsgClearAllRenderTargetsv",
769fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z7rsGetDtv",
779fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z5colorffff",
789fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    "_Z9rsgFinishv",
799fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar  };
809fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar
818a019dd0040bedf5078e4d18e06a244a675b80e8Chih-Hung Hsieh  bool isPresent(std::vector<std::string> &list, const std::string &name) {
829fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    auto lower = std::lower_bound(list.begin(),
839fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar                                  list.end(),
849fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar                                  name);
859fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar
869fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    if (lower != list.end() && name.compare(*lower) == 0)
879fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar      return true;
889fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    return false;
899fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar  }
909fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar
919fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainarpublic:
929fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar  RSIsThreadablePass()
939fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    : ModulePass (ID) {
949fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar      std::sort(nonThreadableFns.begin(), nonThreadableFns.end());
959fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar  }
969fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar
979fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar  virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
989fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    AU.setPreservesAll();
999fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar  }
1009fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar
1019fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar  bool runOnModule(llvm::Module &M) override {
1029fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    bool threadable = true;
1039fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar
1049fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    auto &FunctionList(M.getFunctionList());
1059fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    for (auto &F: FunctionList) {
1069fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar      if (isPresent(nonThreadableFns, F.getName().str())) {
1079fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar        threadable = false;
1089fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar        break;
1099fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar      }
1109fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    }
1119fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar
1129fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    llvm::LLVMContext &context = M.getContext();
1139fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    llvm::MDString *val =
1149fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar      llvm::MDString::get(context, (threadable) ? "yes" : "no");
1159fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    llvm::NamedMDNode *node =
1169fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar        M.getOrInsertNamedMetadata("#rs_is_threadable");
1179fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    node->addOperand(llvm::MDNode::get(context, val));
1189fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar
1199fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar    return false;
1209fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar  }
1219fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar
1229fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar};
1239fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar
1249fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar}
1259fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar
1269fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainarchar RSIsThreadablePass::ID = 0;
1279fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar
1289fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainarnamespace bcc {
1299fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar
1309fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainarllvm::ModulePass *
1319fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga NainarcreateRSIsThreadablePass () {
1329fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar  return new RSIsThreadablePass();
1339fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar}
1349fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar
1359fe081b8bae8a95d903f8fa8dc0a7590ae706606Pirama Arumuga Nainar}
136