summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/radeon/AMDILPrintfConvert.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/radeon/AMDILPrintfConvert.cpp')
-rw-r--r--src/gallium/drivers/radeon/AMDILPrintfConvert.cpp293
1 files changed, 293 insertions, 0 deletions
diff --git a/src/gallium/drivers/radeon/AMDILPrintfConvert.cpp b/src/gallium/drivers/radeon/AMDILPrintfConvert.cpp
new file mode 100644
index 00000000000..95614f477c0
--- /dev/null
+++ b/src/gallium/drivers/radeon/AMDILPrintfConvert.cpp
@@ -0,0 +1,293 @@
+//===-- AMDILPrintfConvert.cpp - Printf Conversion pass --===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//==-----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "PrintfConvert"
+#ifdef DEBUG
+#define DEBUGME (DebugFlag && isCurrentDebugType(DEBUG_TYPE))
+#else
+#define DEBUGME 0
+#endif
+
+#include "AMDILAlgorithms.tpp"
+#include "AMDILKernelManager.h"
+#include "AMDILMachineFunctionInfo.h"
+#include "AMDILModuleInfo.h"
+#include "AMDILTargetMachine.h"
+#include "AMDILUtilityFunctions.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineFunctionAnalysis.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/GlobalVariable.h"
+#include "llvm/Instructions.h"
+#include "llvm/Module.h"
+#include "llvm/Type.h"
+
+#include <cstdio>
+
+using namespace llvm;
+namespace
+{
+ class LLVM_LIBRARY_VISIBILITY AMDILPrintfConvert : public FunctionPass
+ {
+ public:
+ TargetMachine &TM;
+ static char ID;
+ AMDILPrintfConvert(TargetMachine &tm AMDIL_OPT_LEVEL_DECL);
+ ~AMDILPrintfConvert();
+ const char* getPassName() const;
+ bool runOnFunction(Function &F);
+ bool doInitialization(Module &M);
+ bool doFinalization(Module &M);
+ void getAnalysisUsage(AnalysisUsage &AU) const;
+
+ private:
+ bool expandPrintf(BasicBlock::iterator *bbb);
+ AMDILMachineFunctionInfo *mMFI;
+ AMDILKernelManager *mKM;
+ bool mChanged;
+ SmallVector<int64_t, DEFAULT_VEC_SLOTS> bVecMap;
+ };
+ char AMDILPrintfConvert::ID = 0;
+} // anonymouse namespace
+
+namespace llvm
+{
+ FunctionPass*
+ createAMDILPrintfConvert(TargetMachine &tm AMDIL_OPT_LEVEL_DECL)
+ {
+ return new AMDILPrintfConvert(tm AMDIL_OPT_LEVEL_VAR);
+ }
+} // llvm namespace
+AMDILPrintfConvert::AMDILPrintfConvert(TargetMachine &tm AMDIL_OPT_LEVEL_DECL)
+ : FunctionPass(ID), TM(tm)
+{
+}
+AMDILPrintfConvert::~AMDILPrintfConvert()
+{
+}
+ bool
+AMDILPrintfConvert::expandPrintf(BasicBlock::iterator *bbb)
+{
+ Instruction *inst = (*bbb);
+ CallInst *CI = dyn_cast<CallInst>(inst);
+ if (!CI) {
+ return false;
+ }
+ int num_ops = CI->getNumOperands();
+ if (!num_ops) {
+ return false;
+ }
+ if (CI->getOperand(num_ops - 1)->getName() != "printf") {
+ return false;
+ }
+
+ Function *mF = inst->getParent()->getParent();
+ uint64_t bytes = 0;
+ mChanged = true;
+ if (num_ops == 1) {
+ ++(*bbb);
+ Constant *newConst = ConstantInt::getSigned(CI->getType(), bytes);
+ CI->replaceAllUsesWith(newConst);
+ CI->eraseFromParent();
+ return mChanged;
+ }
+ // Deal with the string here
+ Value *op = CI->getOperand(0);
+ ConstantExpr *GEPinst = dyn_cast<ConstantExpr>(op);
+ if (GEPinst) {
+ GlobalVariable *GVar
+ = dyn_cast<GlobalVariable>(GEPinst->getOperand(0));
+ std::string str = "unknown";
+ if (GVar && GVar->hasInitializer()) {
+ ConstantDataArray *CA
+ = dyn_cast<ConstantDataArray>(GVar->getInitializer());
+ str = (CA->isString() ? CA->getAsString() : "unknown");
+ }
+ uint64_t id = (uint64_t)mMFI->addPrintfString(str,
+ getAnalysis<MachineFunctionAnalysis>().getMF()
+ .getMMI().getObjFileInfo<AMDILModuleInfo>().get_printf_offset());
+ std::string name = "___dumpStringID";
+ Function *nF = NULL;
+ std::vector<Type*> types;
+ types.push_back(Type::getInt32Ty(mF->getContext()));
+ nF = mF->getParent()->getFunction(name);
+ if (!nF) {
+ nF = Function::Create(
+ FunctionType::get(
+ Type::getVoidTy(mF->getContext()), types, false),
+ GlobalValue::ExternalLinkage,
+ name, mF->getParent());
+ }
+ Constant *C = ConstantInt::get(
+ Type::getInt32Ty(mF->getContext()), id, false);
+ CallInst *nCI = CallInst::Create(nF, C);
+ nCI->insertBefore(CI);
+ bytes = strlen(str.data());
+ for (uint32_t x = 1, y = num_ops - 1; x < y; ++x) {
+ op = CI->getOperand(x);
+ Type *oType = op->getType();
+ uint32_t eleCount = getNumElements(oType);
+ uint32_t eleSize = (uint32_t)GET_SCALAR_SIZE(oType);
+ if (!eleSize) {
+ // Default size is 32bits.
+ eleSize = 32;
+ }
+ if (!eleCount) {
+ // Default num elements is 1.
+ eleCount = 1;
+ }
+ uint32_t totalSize = eleCount * eleSize;
+ mMFI->addPrintfOperand(str, (x - 1),
+ (uint32_t)totalSize);
+ }
+ }
+ for (uint32_t x = 1, y = num_ops - 1; x < y; ++x) {
+ op = CI->getOperand(x);
+ Type *oType = op->getType();
+ if (oType->isFPOrFPVectorTy()
+ && (oType->getTypeID() != Type::VectorTyID)) {
+ Type *iType = NULL;
+ if (oType->isFloatTy()) {
+ iType = dyn_cast<Type>(
+ Type::getInt32Ty(oType->getContext()));
+ } else {
+ iType = dyn_cast<Type>(
+ Type::getInt64Ty(oType->getContext()));
+ }
+ op = new BitCastInst(op, iType, "printfBitCast", CI);
+ } else if (oType->getTypeID() == Type::VectorTyID) {
+ Type *iType = NULL;
+ uint32_t eleCount = getNumElements(oType);
+ uint32_t eleSize = (uint32_t)GET_SCALAR_SIZE(oType);
+ uint32_t totalSize = eleCount * eleSize;
+ switch (eleSize) {
+ default:
+ eleCount = totalSize / 64;
+ iType = dyn_cast<Type>(
+ Type::getInt64Ty(oType->getContext()));
+ break;
+ case 8:
+ if (eleCount >= 8) {
+ eleCount = totalSize / 64;
+ iType = dyn_cast<Type>(
+ Type::getInt64Ty(oType->getContext()));
+ } else if (eleCount >= 4) {
+ eleCount = 1;
+ iType = dyn_cast<Type>(
+ Type::getInt32Ty(oType->getContext()));
+ } else {
+ eleCount = 1;
+ iType = dyn_cast<Type>(
+ Type::getInt16Ty(oType->getContext()));
+ }
+ break;
+ case 16:
+ if (eleCount >= 4) {
+ eleCount = totalSize / 64;
+ iType = dyn_cast<Type>(
+ Type::getInt64Ty(oType->getContext()));
+ } else {
+ eleCount = 1;
+ iType = dyn_cast<Type>(
+ Type::getInt32Ty(oType->getContext()));
+ }
+ break;
+ }
+ if (eleCount > 1) {
+ iType = dyn_cast<Type>(
+ VectorType::get(iType, eleCount));
+ }
+ op = new BitCastInst(op, iType, "printfBitCast", CI);
+ }
+ char buffer[256];
+ uint32_t size = (uint32_t)GET_SCALAR_SIZE(oType);
+ if (size) {
+ sprintf(buffer, "___dumpBytes_v%db%u",
+ 1,
+ (uint32_t)getNumElements(oType) * (uint32_t)size);
+ } else {
+ const PointerType *PT = dyn_cast<PointerType>(oType);
+ if (PT->getAddressSpace() == 0 &&
+ GET_SCALAR_SIZE(PT->getContainedType(0)) == 8
+ && getNumElements(PT->getContainedType(0)) == 1) {
+ op = new BitCastInst(op,
+ Type::getInt8PtrTy(oType->getContext(),
+ AMDILAS::CONSTANT_ADDRESS),
+ "printfPtrCast", CI);
+
+ sprintf(buffer, "___dumpBytes_v%dbs", 1);
+ } else {
+ op = new PtrToIntInst(op,
+ Type::getInt32Ty(oType->getContext()),
+ "printfPtrCast", CI);
+ sprintf(buffer, "___dumpBytes_v1b32");
+ }
+ }
+ std::vector<Type*> types;
+ types.push_back(op->getType());
+ std::string name = buffer;
+ Function *nF = NULL;
+ nF = mF->getParent()->getFunction(name);
+ if (!nF) {
+ nF = Function::Create(
+ FunctionType::get(
+ Type::getVoidTy(mF->getContext()), types, false),
+ GlobalValue::ExternalLinkage,
+ name, mF->getParent());
+ }
+ CallInst *nCI = CallInst::Create(nF, op);
+ nCI->insertBefore(CI);
+ bytes += (size - 4);
+ }
+ ++(*bbb);
+ Constant *newConst = ConstantInt::getSigned(CI->getType(), bytes);
+ CI->replaceAllUsesWith(newConst);
+ CI->eraseFromParent();
+ return mChanged;
+}
+ bool
+AMDILPrintfConvert::runOnFunction(Function &MF)
+{
+ mChanged = false;
+ mKM = TM.getSubtarget<AMDILSubtarget>().getKernelManager();
+ mMFI = getAnalysis<MachineFunctionAnalysis>().getMF()
+ .getInfo<AMDILMachineFunctionInfo>();
+ bVecMap.clear();
+ safeNestedForEach(MF.begin(), MF.end(), MF.begin()->begin(),
+ std::bind1st(
+ std::mem_fun(
+ &AMDILPrintfConvert::expandPrintf), this));
+ return mChanged;
+}
+
+const char*
+AMDILPrintfConvert::getPassName() const
+{
+ return "AMDIL Printf Conversion Pass";
+}
+bool
+AMDILPrintfConvert::doInitialization(Module &M)
+{
+ return false;
+}
+
+bool
+AMDILPrintfConvert::doFinalization(Module &M)
+{
+ return false;
+}
+
+void
+AMDILPrintfConvert::getAnalysisUsage(AnalysisUsage &AU) const
+{
+ AU.addRequired<MachineFunctionAnalysis>();
+ FunctionPass::getAnalysisUsage(AU);
+ AU.setPreservesAll();
+}