upload android base code part1
This commit is contained in:
parent
e02f198e2d
commit
0a1de6c4b3
48159 changed files with 9071466 additions and 0 deletions
181
android/frameworks/compile/libbcc/lib/RSX86TranslateGEPPass.cpp
Normal file
181
android/frameworks/compile/libbcc/lib/RSX86TranslateGEPPass.cpp
Normal file
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
* Copyright 2016, The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "bcc/Config.h"
|
||||
#include "Assert.h"
|
||||
#include "Log.h"
|
||||
#include "RSTransforms.h"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include <llvm/IR/Function.h>
|
||||
#include <llvm/IR/Instructions.h>
|
||||
#include <llvm/IR/Module.h>
|
||||
#include <llvm/Pass.h>
|
||||
#include <llvm/IR/GetElementPtrTypeIterator.h>
|
||||
|
||||
namespace { // anonymous namespace
|
||||
|
||||
/* This pass translates GEPs that index into structs or arrays of structs to
|
||||
* GEPs with an int8* operand and a byte offset. This translation is done to
|
||||
* enforce on x86 the ARM alignment rule that 64-bit scalars be 8-byte aligned
|
||||
* for structs with such scalars.
|
||||
*/
|
||||
class RSX86TranslateGEPPass : public llvm::FunctionPass {
|
||||
private:
|
||||
static char ID;
|
||||
llvm::LLVMContext *Context;
|
||||
const llvm::DataLayout DL;
|
||||
|
||||
// Walk a GEP instruction and return true if any type indexed is a struct.
|
||||
bool GEPIndexesStructType(const llvm::GetElementPtrInst *GEP) {
|
||||
for (llvm::gep_type_iterator GTI = gep_type_begin(GEP),
|
||||
GTE = gep_type_end(GEP);
|
||||
GTI != GTE; ++GTI) {
|
||||
if (llvm::dyn_cast<llvm::StructType>(*GTI)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Helper method to add two llvm::Value parameters
|
||||
llvm::Value *incrementOffset(llvm::Value *accum, llvm::Value *incr,
|
||||
llvm::Instruction *InsertBefore) {
|
||||
if (accum == nullptr)
|
||||
return incr;
|
||||
return llvm::BinaryOperator::CreateAdd(accum, incr, "", InsertBefore);
|
||||
}
|
||||
|
||||
// Compute the byte offset for a GEP from the GEP's base pointer operand.
|
||||
// Based on visitGetElementPtrInst in llvm/lib/Transforms/Scalar/SROA.cpp.
|
||||
// The difference is that this function handles non-constant array indices and
|
||||
// constructs a sequence of instructions to calculate the offset. These
|
||||
// instructions might not be the most efficient way to calculate this offset,
|
||||
// but we rely on subsequent optimizations to do necessary fold/combine.
|
||||
llvm::Value *computeGEPOffset(llvm::GetElementPtrInst *GEP) {
|
||||
llvm::Value *Offset = nullptr;
|
||||
|
||||
for (llvm::gep_type_iterator GTI = gep_type_begin(GEP),
|
||||
GTE = gep_type_end(GEP);
|
||||
GTI != GTE; ++GTI) {
|
||||
if (llvm::StructType *STy = llvm::dyn_cast<llvm::StructType>(*GTI)) {
|
||||
llvm::ConstantInt *OpC = llvm::dyn_cast<llvm::ConstantInt>(GTI.getOperand());
|
||||
if (!OpC) {
|
||||
ALOGE("Operand for struct type is not constant!");
|
||||
bccAssert(false);
|
||||
}
|
||||
|
||||
// Offset = Offset + EltOffset for index into a struct
|
||||
const llvm::StructLayout *SL = DL.getStructLayout(STy);
|
||||
unsigned EltOffset = SL->getElementOffset(OpC->getZExtValue());
|
||||
llvm::Value *Incr = llvm::ConstantInt::get(
|
||||
llvm::Type::getInt32Ty(*Context), EltOffset);
|
||||
Offset = incrementOffset(Offset, Incr, GEP);
|
||||
} else {
|
||||
// Offset = Offset + Index * EltSize for index into an array or a vector
|
||||
llvm::Value *EltSize = llvm::ConstantInt::get(
|
||||
llvm::Type::getInt32Ty(*Context),
|
||||
DL.getTypeAllocSize(GTI.getIndexedType()));
|
||||
llvm::Value *Incr = llvm::BinaryOperator::CreateMul(
|
||||
GTI.getOperand() /* Index */,
|
||||
EltSize, "", GEP);
|
||||
Offset = incrementOffset(Offset, Incr, GEP);
|
||||
}
|
||||
}
|
||||
|
||||
return Offset;
|
||||
}
|
||||
|
||||
void translateGEP(llvm::GetElementPtrInst *GEP) {
|
||||
// cast GEP pointer operand to int8*
|
||||
llvm::CastInst *Int8Ptr = llvm::CastInst::CreatePointerCast(
|
||||
GEP->getPointerOperand(),
|
||||
llvm::Type::getInt8PtrTy(*Context),
|
||||
"to.int8ptr",
|
||||
GEP);
|
||||
llvm::Value *Indices[1] = {computeGEPOffset(GEP)};
|
||||
|
||||
// index into the int8* based on the byte offset
|
||||
llvm::GetElementPtrInst *Int8PtrGEP = llvm::GetElementPtrInst::Create(
|
||||
llvm::Type::getInt8Ty(*Context), Int8Ptr, llvm::makeArrayRef(Indices),
|
||||
"int8ptr.indexed", GEP);
|
||||
Int8PtrGEP->setIsInBounds(GEP->isInBounds());
|
||||
|
||||
// cast the indexed int8* back to the type of the original GEP
|
||||
llvm::CastInst *OutCast = llvm::CastInst::CreatePointerCast(
|
||||
Int8PtrGEP, GEP->getType(), "to.orig.geptype", GEP);
|
||||
|
||||
GEP->replaceAllUsesWith(OutCast);
|
||||
}
|
||||
|
||||
public:
|
||||
RSX86TranslateGEPPass()
|
||||
: FunctionPass (ID), DL(X86_CUSTOM_DL_STRING) {
|
||||
}
|
||||
|
||||
virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
|
||||
// This pass is run in isolation in a separate pass manager. So setting
|
||||
// AnalysisUsage is unnecessary. Set just for completeness.
|
||||
AU.setPreservesCFG();
|
||||
}
|
||||
|
||||
virtual bool runOnFunction(llvm::Function &F) override {
|
||||
bool changed = false;
|
||||
Context = &F.getParent()->getContext();
|
||||
|
||||
// To avoid updating/deleting instructions while walking a BasicBlock's instructions,
|
||||
// collect the GEPs that need to be translated and process them
|
||||
// subsequently.
|
||||
std::vector<llvm::GetElementPtrInst *> GEPsToHandle;
|
||||
|
||||
for (auto &BB: F) {
|
||||
for (auto &I: BB) {
|
||||
if (auto *GEP = llvm::dyn_cast<llvm::GetElementPtrInst>(&I)) {
|
||||
if (GEPIndexesStructType(GEP)) {
|
||||
GEPsToHandle.push_back(GEP);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto *GEP: GEPsToHandle) {
|
||||
// Translate GEPs and erase them
|
||||
translateGEP(GEP);
|
||||
changed = true;
|
||||
GEP->eraseFromParent();
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
virtual const char *getPassName() const override {
|
||||
return "Translate GEPs on structs, intended for x86 target";
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
char RSX86TranslateGEPPass::ID = 0;
|
||||
|
||||
namespace bcc {
|
||||
|
||||
llvm::FunctionPass *
|
||||
createRSX86TranslateGEPPass() {
|
||||
return new RSX86TranslateGEPPass();
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue