168db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard//===-- SITypeRewriter.cpp - Remove unwanted types ------------------------===// 268db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard// 368db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard// The LLVM Compiler Infrastructure 468db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard// 568db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard// This file is distributed under the University of Illinois Open Source 668db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard// License. See LICENSE.TXT for details. 768db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard// 868db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard//===----------------------------------------------------------------------===// 968db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard// 1068db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard/// \file 1168db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard/// This pass removes performs the following type substitution on all 1268db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard/// non-compute shaders: 1368db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard/// 1468db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard/// v16i8 => i128 1568db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard/// - v16i8 is used for constant memory resource descriptors. This type is 1668db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard/// legal for some compute APIs, and we don't want to declare it as legal 1768db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard/// in the backend, because we want the legalizer to expand all v16i8 1868db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard/// operations. 19e8e33f448e8830590c498ac5101ef8b27446ca3bTom Stellard/// v1* => * 20e8e33f448e8830590c498ac5101ef8b27446ca3bTom Stellard/// - Having v1* types complicates the legalizer and we can easily replace 21e8e33f448e8830590c498ac5101ef8b27446ca3bTom Stellard/// - them with the element type. 2268db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard//===----------------------------------------------------------------------===// 2368db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard 2468db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard#include "AMDGPU.h" 2568db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard#include "llvm/IR/IRBuilder.h" 2636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/IR/InstVisitor.h" 2768db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard 2868db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellardusing namespace llvm; 2968db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard 3068db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellardnamespace { 3168db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard 3268db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellardclass SITypeRewriter : public FunctionPass, 3368db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard public InstVisitor<SITypeRewriter> { 3468db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard 3568db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard static char ID; 3668db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard Module *Mod; 3768db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard Type *v16i8; 38dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Type *v4i32; 3968db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard 4068db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellardpublic: 4168db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard SITypeRewriter() : FunctionPass(ID) { } 42dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines bool doInitialization(Module &M) override; 43dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines bool runOnFunction(Function &F) override; 44dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const char *getPassName() const override { 4568db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard return "SI Type Rewriter"; 4668db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard } 4768db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard void visitLoadInst(LoadInst &I); 4868db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard void visitCallInst(CallInst &I); 4968db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard void visitBitCast(BitCastInst &I); 5068db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard}; 5168db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard 5268db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard} // End anonymous namespace 5368db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard 5468db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellardchar SITypeRewriter::ID = 0; 5568db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard 5668db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellardbool SITypeRewriter::doInitialization(Module &M) { 5768db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard Mod = &M; 5868db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard v16i8 = VectorType::get(Type::getInt8Ty(M.getContext()), 16); 59dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines v4i32 = VectorType::get(Type::getInt32Ty(M.getContext()), 4); 6068db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard return false; 6168db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard} 6268db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard 6368db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellardbool SITypeRewriter::runOnFunction(Function &F) { 6468db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard AttributeSet Set = F.getAttributes(); 6568db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard Attribute A = Set.getAttribute(AttributeSet::FunctionIndex, "ShaderType"); 6668db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard 6768db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard unsigned ShaderType = ShaderType::COMPUTE; 6868db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard if (A.isStringAttribute()) { 6968db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard StringRef Str = A.getValueAsString(); 7068db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard Str.getAsInteger(0, ShaderType); 7168db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard } 7236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (ShaderType == ShaderType::COMPUTE) 7336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return false; 7468db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard 7568db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard visit(F); 7636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines visit(F); 7768db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard 7868db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard return false; 7968db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard} 8068db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard 8168db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellardvoid SITypeRewriter::visitLoadInst(LoadInst &I) { 8268db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard Value *Ptr = I.getPointerOperand(); 8368db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard Type *PtrTy = Ptr->getType(); 8468db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard Type *ElemTy = PtrTy->getPointerElementType(); 8568db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard IRBuilder<> Builder(&I); 8668db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard if (ElemTy == v16i8) { 87dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Value *BitCast = Builder.CreateBitCast(Ptr, 88dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines PointerType::get(v4i32,PtrTy->getPointerAddressSpace())); 8968db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard LoadInst *Load = Builder.CreateLoad(BitCast); 9068db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard SmallVector <std::pair<unsigned, MDNode*>, 8> MD; 9168db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard I.getAllMetadataOtherThanDebugLoc(MD); 9268db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard for (unsigned i = 0, e = MD.size(); i != e; ++i) { 9368db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard Load->setMetadata(MD[i].first, MD[i].second); 9468db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard } 9568db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard Value *BitCastLoad = Builder.CreateBitCast(Load, I.getType()); 9668db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard I.replaceAllUsesWith(BitCastLoad); 9768db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard I.eraseFromParent(); 9868db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard } 9968db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard} 10068db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard 10168db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellardvoid SITypeRewriter::visitCallInst(CallInst &I) { 10268db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard IRBuilder<> Builder(&I); 103dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 10468db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard SmallVector <Value*, 8> Args; 10568db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard SmallVector <Type*, 8> Types; 10668db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard bool NeedToReplace = false; 10768db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard Function *F = I.getCalledFunction(); 10868db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard std::string Name = F->getName().str(); 10968db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard for (unsigned i = 0, e = I.getNumArgOperands(); i != e; ++i) { 11068db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard Value *Arg = I.getArgOperand(i); 11168db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard if (Arg->getType() == v16i8) { 112dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Args.push_back(Builder.CreateBitCast(Arg, v4i32)); 113dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Types.push_back(v4i32); 11468db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard NeedToReplace = true; 115dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Name = Name + ".v4i32"; 116e8e33f448e8830590c498ac5101ef8b27446ca3bTom Stellard } else if (Arg->getType()->isVectorTy() && 117e8e33f448e8830590c498ac5101ef8b27446ca3bTom Stellard Arg->getType()->getVectorNumElements() == 1 && 118e8e33f448e8830590c498ac5101ef8b27446ca3bTom Stellard Arg->getType()->getVectorElementType() == 119e8e33f448e8830590c498ac5101ef8b27446ca3bTom Stellard Type::getInt32Ty(I.getContext())){ 120e8e33f448e8830590c498ac5101ef8b27446ca3bTom Stellard Type *ElementTy = Arg->getType()->getVectorElementType(); 121e8e33f448e8830590c498ac5101ef8b27446ca3bTom Stellard std::string TypeName = "i32"; 122cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines InsertElementInst *Def = cast<InsertElementInst>(Arg); 123e8e33f448e8830590c498ac5101ef8b27446ca3bTom Stellard Args.push_back(Def->getOperand(1)); 124e8e33f448e8830590c498ac5101ef8b27446ca3bTom Stellard Types.push_back(ElementTy); 125e8e33f448e8830590c498ac5101ef8b27446ca3bTom Stellard std::string VecTypeName = "v1" + TypeName; 126e8e33f448e8830590c498ac5101ef8b27446ca3bTom Stellard Name = Name.replace(Name.find(VecTypeName), VecTypeName.length(), TypeName); 127e8e33f448e8830590c498ac5101ef8b27446ca3bTom Stellard NeedToReplace = true; 12868db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard } else { 12968db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard Args.push_back(Arg); 13068db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard Types.push_back(Arg->getType()); 13168db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard } 13268db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard } 13368db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard 13468db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard if (!NeedToReplace) { 13568db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard return; 13668db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard } 13768db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard Function *NewF = Mod->getFunction(Name); 13868db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard if (!NewF) { 13968db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard NewF = Function::Create(FunctionType::get(F->getReturnType(), Types, false), GlobalValue::ExternalLinkage, Name, Mod); 14068db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard NewF->setAttributes(F->getAttributes()); 14168db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard } 14268db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard I.replaceAllUsesWith(Builder.CreateCall(NewF, Args)); 14368db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard I.eraseFromParent(); 14468db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard} 14568db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard 14668db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellardvoid SITypeRewriter::visitBitCast(BitCastInst &I) { 14768db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard IRBuilder<> Builder(&I); 148dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (I.getDestTy() != v4i32) { 14968db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard return; 15068db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard } 15168db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard 15268db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard if (BitCastInst *Op = dyn_cast<BitCastInst>(I.getOperand(0))) { 153dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (Op->getSrcTy() == v4i32) { 15468db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard I.replaceAllUsesWith(Op->getOperand(0)); 15568db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard I.eraseFromParent(); 15668db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard } 15768db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard } 15868db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard} 15968db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard 16068db37b952be497c94c7aa98cf26f3baadb5afd3Tom StellardFunctionPass *llvm::createSITypeRewriter() { 16168db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard return new SITypeRewriter(); 16268db37b952be497c94c7aa98cf26f3baadb5afd3Tom Stellard} 163