19e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar/* 29e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar * Copyright 2016, The Android Open Source Project 39e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar * 49e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar * Licensed under the Apache License, Version 2.0 (the "License"); 59e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar * you may not use this file except in compliance with the License. 69e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar * You may obtain a copy of the License at 79e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar * 89e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar * http://www.apache.org/licenses/LICENSE-2.0 99e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar * 109e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar * Unless required by applicable law or agreed to in writing, software 119e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar * distributed under the License is distributed on an "AS IS" BASIS, 129e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar * See the License for the specific language governing permissions and 149e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar * limitations under the License. 159e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar */ 169e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar 179e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar#include "bcc/Assert.h" 189e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar#include "bcc/Config/Config.h" 199e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar#include "bcc/Support/Log.h" 209e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar#include "bcc/Renderscript/RSTransforms.h" 219e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar 229e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar#include <cstdlib> 239e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar 249e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar#include <llvm/IR/Function.h> 259e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar#include <llvm/IR/Instructions.h> 269e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar#include <llvm/IR/Module.h> 279e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar#include <llvm/Pass.h> 289e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar#include <llvm/IR/GetElementPtrTypeIterator.h> 299e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar 309e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainarnamespace { // anonymous namespace 319e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar 329e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar/* This pass translates GEPs that index into structs or arrays of structs to 339e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar * GEPs with an int8* operand and a byte offset. This translation is done to 349e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar * enforce on x86 the ARM alignment rule that 64-bit scalars be 8-byte aligned 359e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar * for structs with such scalars. 369e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar */ 379e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainarclass RSX86TranslateGEPPass : public llvm::FunctionPass { 389e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainarprivate: 399e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar static char ID; 409e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar llvm::LLVMContext *Context; 419e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar const llvm::DataLayout DL; 429e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar 439e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar // Walk a GEP instruction and return true if any type indexed is a struct. 449e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar bool GEPIndexesStructType(const llvm::GetElementPtrInst *GEP) { 459e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar for (llvm::gep_type_iterator GTI = gep_type_begin(GEP), 469e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar GTE = gep_type_end(GEP); 479e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar GTI != GTE; ++GTI) { 489e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar if (llvm::dyn_cast<llvm::StructType>(*GTI)) { 499e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar return true; 509e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar } 519e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar } 529e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar return false; 539e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar } 549e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar 559e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar // Helper method to add two llvm::Value parameters 569e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar llvm::Value *incrementOffset(llvm::Value *accum, llvm::Value *incr, 579e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar llvm::Instruction *InsertBefore) { 589e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar if (accum == nullptr) 599e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar return incr; 609e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar return llvm::BinaryOperator::CreateAdd(accum, incr, "", InsertBefore); 619e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar } 629e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar 639e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar // Compute the byte offset for a GEP from the GEP's base pointer operand. 649e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar // Based on visitGetElementPtrInst in llvm/lib/Transforms/Scalar/SROA.cpp. 659e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar // The difference is that this function handles non-constant array indices and 669e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar // constructs a sequence of instructions to calculate the offset. These 679e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar // instructions might not be the most efficient way to calculate this offset, 689e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar // but we rely on subsequent optimizations to do necessary fold/combine. 699e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar llvm::Value *computeGEPOffset(llvm::GetElementPtrInst *GEP) { 709e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar llvm::Value *Offset = nullptr; 719e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar 729e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar for (llvm::gep_type_iterator GTI = gep_type_begin(GEP), 739e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar GTE = gep_type_end(GEP); 749e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar GTI != GTE; ++GTI) { 759e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar if (llvm::StructType *STy = llvm::dyn_cast<llvm::StructType>(*GTI)) { 769e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar llvm::ConstantInt *OpC = llvm::dyn_cast<llvm::ConstantInt>(GTI.getOperand()); 779e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar if (!OpC) { 789e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar ALOGE("Operand for struct type is not constant!"); 799e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar bccAssert(false); 809e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar } 819e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar 829e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar // Offset = Offset + EltOffset for index into a struct 839e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar const llvm::StructLayout *SL = DL.getStructLayout(STy); 849e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar unsigned EltOffset = SL->getElementOffset(OpC->getZExtValue()); 859e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar llvm::Value *Incr = llvm::ConstantInt::get( 869e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar llvm::Type::getInt32Ty(*Context), EltOffset); 879e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar Offset = incrementOffset(Offset, Incr, GEP); 889e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar } else { 899e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar // Offset = Offset + Index * EltSize for index into an array or a vector 909e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar llvm::Value *EltSize = llvm::ConstantInt::get( 919e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar llvm::Type::getInt32Ty(*Context), 929e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar DL.getTypeAllocSize(GTI.getIndexedType())); 939e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar llvm::Value *Incr = llvm::BinaryOperator::CreateMul( 949e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar GTI.getOperand() /* Index */, 959e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar EltSize, "", GEP); 969e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar Offset = incrementOffset(Offset, Incr, GEP); 979e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar } 989e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar } 999e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar 1009e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar return Offset; 1019e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar } 1029e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar 1039e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar void translateGEP(llvm::GetElementPtrInst *GEP) { 1049e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar // cast GEP pointer operand to int8* 1059e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar llvm::CastInst *Int8Ptr = llvm::CastInst::CreatePointerCast( 1069e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar GEP->getPointerOperand(), 1079e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar llvm::Type::getInt8PtrTy(*Context), 1089e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar "to.int8ptr", 1099e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar GEP); 1109e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar llvm::Value *Indices[1] = {computeGEPOffset(GEP)}; 1119e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar 1129e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar // index into the int8* based on the byte offset 1139e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar llvm::GetElementPtrInst *Int8PtrGEP = llvm::GetElementPtrInst::Create( 1149e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar llvm::Type::getInt8Ty(*Context), Int8Ptr, llvm::makeArrayRef(Indices), 1159e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar "int8ptr.indexed", GEP); 1169e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar Int8PtrGEP->setIsInBounds(GEP->isInBounds()); 1179e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar 1189e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar // cast the indexed int8* back to the type of the original GEP 1199e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar llvm::CastInst *OutCast = llvm::CastInst::CreatePointerCast( 1209e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar Int8PtrGEP, GEP->getType(), "to.orig.geptype", GEP); 1219e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar 1229e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar GEP->replaceAllUsesWith(OutCast); 1239e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar } 1249e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar 1259e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainarpublic: 1269e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar RSX86TranslateGEPPass() 1279e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar : FunctionPass (ID), DL(X86_CUSTOM_DL_STRING) { 1289e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar } 1299e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar 1309e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const override { 1319e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar // This pass is run in isolation in a separate pass manager. So setting 1329e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar // AnalysisUsage is unnecessary. Set just for completeness. 1339e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar AU.setPreservesCFG(); 1349e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar } 1359e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar 1369e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar virtual bool runOnFunction(llvm::Function &F) override { 1379e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar bool changed = false; 1389e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar Context = &F.getParent()->getContext(); 1399e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar 1409e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar // To avoid updating/deleting instructions while walking a BasicBlock's instructions, 1419e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar // collect the GEPs that need to be translated and process them 1429e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar // subsequently. 1439e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar std::vector<llvm::GetElementPtrInst *> GEPsToHandle; 1449e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar 1459e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar for (auto &BB: F) { 1469e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar for (auto &I: BB) { 1479e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar if (auto *GEP = llvm::dyn_cast<llvm::GetElementPtrInst>(&I)) { 1489e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar if (GEPIndexesStructType(GEP)) { 1499e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar GEPsToHandle.push_back(GEP); 1509e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar } 1519e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar } 1529e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar } 1539e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar } 1549e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar 1559e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar for (auto *GEP: GEPsToHandle) { 1569e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar // Translate GEPs and erase them 1579e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar translateGEP(GEP); 1589e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar changed = true; 1599e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar GEP->eraseFromParent(); 1609e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar } 1619e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar 1629e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar return changed; 1639e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar } 1649e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar 1659e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar virtual const char *getPassName() const override { 1669e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar return "Translate GEPs on structs, intended for x86 target"; 1679e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar } 1689e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar}; 1699e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar 1709e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar} 1719e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar 1729e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainarchar RSX86TranslateGEPPass::ID = 0; 1739e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar 1749e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainarnamespace bcc { 1759e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar 1769e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainarllvm::FunctionPass * 1779e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga NainarcreateRSX86TranslateGEPPass() { 1789e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar return new RSX86TranslateGEPPass(); 1799e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar} 1809e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar 1819e0f8f0c8965834de02d007bb30e1dc950cf9762Pirama Arumuga Nainar} 182