From 059a56bddb6bd769632e5999cb23c7bdcb79bea1 Mon Sep 17 00:00:00 2001 From: Tom Stellard Date: Mon, 17 Sep 2012 19:06:25 +0000 Subject: [PATCH] radeon/llvm: Move kernel arg lowering into R600TargetLowering class --- .../drivers/radeon/AMDGPUISelLowering.cpp | 2 - .../drivers/radeon/AMDGPUTargetMachine.cpp | 5 - src/gallium/drivers/radeon/Makefile.sources | 1 - .../drivers/radeon/R600ISelLowering.cpp | 28 ++ src/gallium/drivers/radeon/R600ISelLowering.h | 7 + .../drivers/radeon/R600KernelParameters.cpp | 462 ------------------ 6 files changed, 35 insertions(+), 470 deletions(-) delete mode 100644 src/gallium/drivers/radeon/R600KernelParameters.cpp diff --git a/src/gallium/drivers/radeon/AMDGPUISelLowering.cpp b/src/gallium/drivers/radeon/AMDGPUISelLowering.cpp index 59daf77503e..3f9c82076f0 100644 --- a/src/gallium/drivers/radeon/AMDGPUISelLowering.cpp +++ b/src/gallium/drivers/radeon/AMDGPUISelLowering.cpp @@ -53,8 +53,6 @@ SDValue AMDGPUTargetLowering::LowerFormalArguments( DebugLoc DL, SelectionDAG &DAG, SmallVectorImpl &InVals) const { - // Lowering of arguments happens in R600LowerKernelParameters, so we can - // ignore the arguments here. for (unsigned i = 0, e = Ins.size(); i < e; ++i) { InVals.push_back(SDValue()); } diff --git a/src/gallium/drivers/radeon/AMDGPUTargetMachine.cpp b/src/gallium/drivers/radeon/AMDGPUTargetMachine.cpp index 2d1ca068905..c1b68403379 100644 --- a/src/gallium/drivers/radeon/AMDGPUTargetMachine.cpp +++ b/src/gallium/drivers/radeon/AMDGPUTargetMachine.cpp @@ -95,11 +95,6 @@ TargetPassConfig *AMDGPUTargetMachine::createPassConfig(PassManagerBase &PM) { bool AMDGPUPassConfig::addPreISel() { - const AMDGPUSubtarget &ST = TM->getSubtarget(); - if (ST.device()->getGeneration() <= AMDGPUDeviceInfo::HD6XXX) { - PM->add(createR600KernelParametersPass( - getAMDGPUTargetMachine().getTargetData())); - } return false; } diff --git a/src/gallium/drivers/radeon/Makefile.sources b/src/gallium/drivers/radeon/Makefile.sources index f387636270c..4b0699b9e16 100644 --- a/src/gallium/drivers/radeon/Makefile.sources +++ b/src/gallium/drivers/radeon/Makefile.sources @@ -65,7 +65,6 @@ CPP_SOURCES := \ R600ExpandSpecialInstrs.cpp \ R600ISelLowering.cpp \ R600InstrInfo.cpp \ - R600KernelParameters.cpp \ R600MachineFunctionInfo.cpp \ R600RegisterInfo.cpp \ SIAssignInterpRegs.cpp \ diff --git a/src/gallium/drivers/radeon/R600ISelLowering.cpp b/src/gallium/drivers/radeon/R600ISelLowering.cpp index 5a82920c377..dc75a450bdc 100644 --- a/src/gallium/drivers/radeon/R600ISelLowering.cpp +++ b/src/gallium/drivers/radeon/R600ISelLowering.cpp @@ -16,6 +16,7 @@ #include "R600Defines.h" #include "R600InstrInfo.h" #include "R600MachineFunctionInfo.h" +#include "llvm/Argument.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/SelectionDAG.h" @@ -576,3 +577,30 @@ SDValue R600TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const Cond); return Cond; } + +// XXX Only kernel functions are supporte, so we can assume for now that +// every function is a kernel function, but in the future we should use +// separate calling conventions for kernel and non-kernel functions. +// Only kernel functions are supported, so we can assume for now +SDValue R600TargetLowering::LowerFormalArguments( + SDValue Chain, + CallingConv::ID CallConv, + bool isVarArg, + const SmallVectorImpl &Ins, + DebugLoc DL, SelectionDAG &DAG, + SmallVectorImpl &InVals) const +{ + unsigned ParamOffsetBytes = 36; + for (unsigned i = 0, e = Ins.size(); i < e; ++i) { + EVT VT = Ins[i].VT; + PointerType *PtrTy = PointerType::get(VT.getTypeForEVT(*DAG.getContext()), + AMDGPUAS::PARAM_I_ADDRESS); + SDValue Arg = DAG.getLoad(VT, DL, DAG.getRoot(), + DAG.getConstant(ParamOffsetBytes, MVT::i32), + MachinePointerInfo(new Argument(PtrTy)), + false, false, false, 4); + InVals.push_back(Arg); + ParamOffsetBytes += (VT.getStoreSize()); + } + return Chain; +} diff --git a/src/gallium/drivers/radeon/R600ISelLowering.h b/src/gallium/drivers/radeon/R600ISelLowering.h index 49ea272502e..f2999a30aca 100644 --- a/src/gallium/drivers/radeon/R600ISelLowering.h +++ b/src/gallium/drivers/radeon/R600ISelLowering.h @@ -30,6 +30,13 @@ public: void ReplaceNodeResults(SDNode * N, SmallVectorImpl &Results, SelectionDAG &DAG) const; + virtual SDValue LowerFormalArguments( + SDValue Chain, + CallingConv::ID CallConv, + bool isVarArg, + const SmallVectorImpl &Ins, + DebugLoc DL, SelectionDAG &DAG, + SmallVectorImpl &InVals) const; private: const R600InstrInfo * TII; diff --git a/src/gallium/drivers/radeon/R600KernelParameters.cpp b/src/gallium/drivers/radeon/R600KernelParameters.cpp deleted file mode 100644 index ef0fc458480..00000000000 --- a/src/gallium/drivers/radeon/R600KernelParameters.cpp +++ /dev/null @@ -1,462 +0,0 @@ -//===-- R600KernelParameters.cpp - Lower kernel function arguments --------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This pass lowers kernel function arguments to loads from the vertex buffer. -// -// Kernel arguemnts are stored in the vertex buffer at an offset of 9 dwords, -// so arg0 needs to be loaded from VTX_BUFFER[9] and arg1 is loaded from -// VTX_BUFFER[10], etc. -// -//===----------------------------------------------------------------------===// - -#include "AMDGPU.h" -#include "AMDIL.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/Constants.h" -#include "llvm/Function.h" -#include "llvm/Intrinsics.h" -#include "llvm/Metadata.h" -#include "llvm/Module.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Support/IRBuilder.h" -#include "llvm/Support/TypeBuilder.h" - -#include -#include - -using namespace llvm; - -namespace { - -#define CONSTANT_CACHE_SIZE_DW 127 - -class R600KernelParameters : public FunctionPass { - const TargetData *TD; - LLVMContext* Context; - Module *Mod; - - struct Param { - Param() : Val(NULL), PtrVal(NULL), OffsetInDW(0), SizeInDW(0), - IsIndirect(true), SpecialID(0) {} - - Value* Val; - Value* PtrVal; - int OffsetInDW; - int SizeInDW; - - bool IsIndirect; - - std::string SpecialType; - int SpecialID; - - int End() { return OffsetInDW + SizeInDW; } - // The first 9 dwords are reserved for the grid sizes. - int getRatOffset() { return 9 + OffsetInDW; } - }; - - std::vector Params; - - bool IsOpenCLKernel(const Function *Fun); - int getLastSpecialID(const std::string& TypeName); - - int getListSize(); - void AddParam(Argument *Arg); - int CalculateArgumentSize(Argument *Arg); - void RunAna(Function *Fun); - void Replace(Function *Fun); - bool IsIndirect(Value *Val, std::set &Visited); - void Propagate(Function* Fun); - void Propagate(Value *V, const Twine &Name, bool IsIndirect = true); - Value* ConstantRead(Function *Fun, Param &P); - Value* handleSpecial(Function *Fun, Param &P); - bool IsSpecialType(Type *T); - std::string getSpecialTypeName(Type *T); -public: - static char ID; - R600KernelParameters() : FunctionPass(ID) {}; - R600KernelParameters(const TargetData* TD) : FunctionPass(ID), TD(TD) {} - bool runOnFunction (Function &F); - void getAnalysisUsage(AnalysisUsage &AU) const; - const char *getPassName() const; - bool doInitialization(Module &M); - bool doFinalization(Module &M); -}; - -char R600KernelParameters::ID = 0; - -static RegisterPass X("kerparam", - "OpenCL Kernel Parameter conversion", false, false); - -bool R600KernelParameters::IsOpenCLKernel(const Function* Fun) { - Module *Mod = const_cast(Fun)->getParent(); - NamedMDNode * MD = Mod->getOrInsertNamedMetadata("opencl.kernels"); - - if (!MD || !MD->getNumOperands()) { - return false; - } - - for (int i = 0; i < int(MD->getNumOperands()); i++) { - if (!MD->getOperand(i) || !MD->getOperand(i)->getOperand(0)) { - continue; - } - - assert(MD->getOperand(i)->getNumOperands() == 1); - - if (MD->getOperand(i)->getOperand(0)->getName() == Fun->getName()) { - return true; - } - } - - return false; -} - -int R600KernelParameters::getLastSpecialID(const std::string &TypeName) { - int LastID = -1; - - for (std::vector::iterator i = Params.begin(); i != Params.end(); i++) { - if (i->SpecialType == TypeName) { - LastID = i->SpecialID; - } - } - - return LastID; -} - -int R600KernelParameters::getListSize() { - if (Params.size() == 0) { - return 0; - } - - return Params.back().End(); -} - -bool R600KernelParameters::IsIndirect(Value *Val, std::set &Visited) { - //XXX Direct parameters are not supported yet, so return true here. - return true; -#if 0 - if (isa(Val)) { - return false; - } - - if (isa(Val->getType())) { - assert(0 && "Internal error"); - return false; - } - - if (Visited.count(Val)) { - return false; - } - - Visited.insert(Val); - - if (isa(Val)) { - getElementPtrInst* GEP = dyn_cast(Val); - getElementPtrInst::op_iterator I = GEP->op_begin(); - - for (++I; I != GEP->op_end(); ++I) { - if (!isa(*I)) { - return true; - } - } - } - - for (Value::use_iterator I = Val->use_begin(); i != Val->use_end(); ++I) { - Value* V2 = dyn_cast(*I); - - if (V2) { - if (IsIndirect(V2, Visited)) { - return true; - } - } - } - - return false; -#endif -} - -void R600KernelParameters::AddParam(Argument *Arg) { - Param P; - - P.Val = dyn_cast(Arg); - P.OffsetInDW = getListSize(); - P.SizeInDW = CalculateArgumentSize(Arg); - - if (isa(Arg->getType()) && Arg->hasByValAttr()) { - std::set Visited; - P.IsIndirect = IsIndirect(P.Val, Visited); - } - - Params.push_back(P); -} - -int R600KernelParameters::CalculateArgumentSize(Argument *Arg) { - Type* T = Arg->getType(); - - if (Arg->hasByValAttr() && dyn_cast(T)) { - T = dyn_cast(T)->getElementType(); - } - - int StoreSizeInDW = (TD->getTypeStoreSize(T) + 3)/4; - - assert(StoreSizeInDW); - - return StoreSizeInDW; -} - - -void R600KernelParameters::RunAna(Function* Fun) { - assert(IsOpenCLKernel(Fun)); - - for (Function::arg_iterator I = Fun->arg_begin(); I != Fun->arg_end(); ++I) { - AddParam(I); - } - -} - -void R600KernelParameters::Replace(Function* Fun) { - for (std::vector::iterator I = Params.begin(); I != Params.end(); ++I) { - Value *NewVal; - - if (IsSpecialType(I->Val->getType())) { - NewVal = handleSpecial(Fun, *I); - } else { - NewVal = ConstantRead(Fun, *I); - } - if (NewVal) { - I->Val->replaceAllUsesWith(NewVal); - } - } -} - -void R600KernelParameters::Propagate(Function* Fun) { - for (std::vector::iterator I = Params.begin(); I != Params.end(); ++I) { - if (I->PtrVal) { - Propagate(I->PtrVal, I->Val->getName(), I->IsIndirect); - } - } -} - -void R600KernelParameters::Propagate(Value* V, const Twine& Name, bool IsIndirect) { - LoadInst* Load = dyn_cast(V); - GetElementPtrInst *GEP = dyn_cast(V); - - unsigned Addrspace; - - if (IsIndirect) { - Addrspace = AMDGPUAS::PARAM_I_ADDRESS; - } else { - Addrspace = AMDGPUAS::PARAM_D_ADDRESS; - } - - if (GEP && GEP->getType()->getAddressSpace() != Addrspace) { - Value *Op = GEP->getPointerOperand(); - - if (dyn_cast(Op->getType())->getAddressSpace() != Addrspace) { - Op = new BitCastInst(Op, PointerType::get(dyn_cast( - Op->getType())->getElementType(), Addrspace), - Name, dyn_cast(V)); - } - - std::vector Params(GEP->idx_begin(), GEP->idx_end()); - - GetElementPtrInst* GEP2 = GetElementPtrInst::Create(Op, Params, Name, - dyn_cast(V)); - GEP2->setIsInBounds(GEP->isInBounds()); - V = dyn_cast(GEP2); - GEP->replaceAllUsesWith(GEP2); - GEP->eraseFromParent(); - Load = NULL; - } - - if (Load) { - ///normally at this point we have the right address space - if (Load->getPointerAddressSpace() != Addrspace) { - Value *OrigPtr = Load->getPointerOperand(); - PointerType *OrigPtrType = dyn_cast(OrigPtr->getType()); - - Type* NewPtrType = PointerType::get(OrigPtrType->getElementType(), - Addrspace); - - Value* NewPtr = OrigPtr; - - if (OrigPtr->getType() != NewPtrType) { - NewPtr = new BitCastInst(OrigPtr, NewPtrType, "prop_cast", Load); - } - - Value* new_Load = new LoadInst(NewPtr, Name, Load); - Load->replaceAllUsesWith(new_Load); - Load->eraseFromParent(); - } - - return; - } - - std::vector Users(V->use_begin(), V->use_end()); - - for (int i = 0; i < int(Users.size()); i++) { - Value* V2 = dyn_cast(Users[i]); - - if (V2) { - Propagate(V2, Name, IsIndirect); - } - } -} - -Value* R600KernelParameters::ConstantRead(Function *Fun, Param &P) { - assert(Fun->front().begin() != Fun->front().end()); - - Instruction *FirstInst = Fun->front().begin(); - IRBuilder <> Builder (FirstInst); -/* First 3 dwords are reserved for the dimmension info */ - - if (!P.Val->hasNUsesOrMore(1)) { - return NULL; - } - unsigned Addrspace; - - if (P.IsIndirect) { - Addrspace = AMDGPUAS::PARAM_I_ADDRESS; - } else { - Addrspace = AMDGPUAS::PARAM_D_ADDRESS; - } - - Argument *Arg = dyn_cast(P.Val); - Type * ArgType = P.Val->getType(); - PointerType * ArgPtrType = dyn_cast(P.Val->getType()); - - if (ArgPtrType && Arg->hasByValAttr()) { - Value* ParamAddrSpacePtr = ConstantPointerNull::get( - PointerType::get(Type::getInt32Ty(*Context), - Addrspace)); - Value* ParamPtr = GetElementPtrInst::Create(ParamAddrSpacePtr, - ConstantInt::get(Type::getInt32Ty(*Context), - P.getRatOffset()), Arg->getName(), - FirstInst); - ParamPtr = new BitCastInst(ParamPtr, - PointerType::get(ArgPtrType->getElementType(), - Addrspace), - Arg->getName(), FirstInst); - P.PtrVal = ParamPtr; - return ParamPtr; - } else { - Value *ParamAddrSpacePtr = ConstantPointerNull::get(PointerType::get( - ArgType, Addrspace)); - - Value *ParamPtr = Builder.CreateGEP(ParamAddrSpacePtr, - ConstantInt::get(Type::getInt32Ty(*Context), P.getRatOffset()), - Arg->getName()); - - Value *Param_Value = Builder.CreateLoad(ParamPtr, Arg->getName()); - - return Param_Value; - } -} - -Value* R600KernelParameters::handleSpecial(Function* Fun, Param& P) { - std::string Name = getSpecialTypeName(P.Val->getType()); - int ID; - - assert(!Name.empty()); - - if (Name == "image2d_t" || Name == "image3d_t") { - int LastID = std::max(getLastSpecialID("image2d_t"), - getLastSpecialID("image3d_t")); - - if (LastID == -1) { - ID = 2; ///ID0 and ID1 are used internally by the driver - } else { - ID = LastID + 1; - } - } else if (Name == "sampler_t") { - int LastID = getLastSpecialID("sampler_t"); - - if (LastID == -1) { - ID = 0; - } else { - ID = LastID + 1; - } - } else { - ///TODO: give some error message - return NULL; - } - - P.SpecialType = Name; - P.SpecialID = ID; - - Instruction *FirstInst = Fun->front().begin(); - - return new IntToPtrInst(ConstantInt::get(Type::getInt32Ty(*Context), - P.SpecialID), P.Val->getType(), - "resourceID", FirstInst); -} - - -bool R600KernelParameters::IsSpecialType(Type* T) { - return !getSpecialTypeName(T).empty(); -} - -std::string R600KernelParameters::getSpecialTypeName(Type* T) { - PointerType *PT = dyn_cast(T); - StructType *ST = NULL; - - if (PT) { - ST = dyn_cast(PT->getElementType()); - } - - if (ST) { - std::string Prefix = "struct.opencl_builtin_type_"; - - std::string Name = ST->getName().str(); - - if (Name.substr(0, Prefix.length()) == Prefix) { - return Name.substr(Prefix.length(), Name.length()); - } - } - - return ""; -} - - -bool R600KernelParameters::runOnFunction (Function &F) { - if (!IsOpenCLKernel(&F)) { - return false; - } - - RunAna(&F); - Replace(&F); - Propagate(&F); - - return false; -} - -void R600KernelParameters::getAnalysisUsage(AnalysisUsage &AU) const { - FunctionPass::getAnalysisUsage(AU); - AU.setPreservesAll(); -} - -const char *R600KernelParameters::getPassName() const { - return "OpenCL Kernel parameter conversion to memory"; -} - -bool R600KernelParameters::doInitialization(Module &M) { - Context = &M.getContext(); - Mod = &M; - - return false; -} - -bool R600KernelParameters::doFinalization(Module &M) { - return false; -} - -} // End anonymous namespace - -FunctionPass* llvm::createR600KernelParametersPass(const TargetData* TD) { - return new R600KernelParameters(TD); -}