Path: blob/main/contrib/llvm-project/llvm/lib/Target/NVPTX/NVPTXForwardParams.cpp
213799 views
//- NVPTXForwardParams.cpp - NVPTX Forward Device Params Removing Local Copy -//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// PTX supports 2 methods of accessing device function parameters:9//10// - "simple" case: If a parameters is only loaded, and all loads can address11// the parameter via a constant offset, then the parameter may be loaded via12// the ".param" address space. This case is not possible if the parameters13// is stored to or has it's address taken. This method is preferable when14// possible. Ex:15//16// ld.param.u32 %r1, [foo_param_1];17// ld.param.u32 %r2, [foo_param_1+4];18//19// - "move param" case: For more complex cases the address of the param may be20// placed in a register via a "mov" instruction. This "mov" also implicitly21// moves the param to the ".local" address space and allows for it to be22// written to. This essentially defers the responsibilty of the byval copy23// to the PTX calling convention.24//25// mov.b64 %rd1, foo_param_0;26// st.local.u32 [%rd1], 42;27// add.u64 %rd3, %rd1, %rd2;28// ld.local.u32 %r2, [%rd3];29//30// In NVPTXLowerArgs and SelectionDAG, we pessimistically assume that all31// parameters will use the "move param" case and the local address space. This32// pass is responsible for switching to the "simple" case when possible, as it33// is more efficient.34//35// We do this by simply traversing uses of the param "mov" instructions an36// trivially checking if they are all loads.37//38//===----------------------------------------------------------------------===//3940#include "NVPTX.h"41#include "llvm/ADT/SmallVector.h"42#include "llvm/CodeGen/MachineFunctionPass.h"43#include "llvm/CodeGen/MachineInstr.h"44#include "llvm/CodeGen/MachineOperand.h"45#include "llvm/CodeGen/MachineRegisterInfo.h"46#include "llvm/CodeGen/TargetRegisterInfo.h"47#include "llvm/Support/ErrorHandling.h"4849using namespace llvm;5051static bool traverseMoveUse(MachineInstr &U, const MachineRegisterInfo &MRI,52SmallVectorImpl<MachineInstr *> &RemoveList,53SmallVectorImpl<MachineInstr *> &LoadInsts) {54switch (U.getOpcode()) {55case NVPTX::LD_i16:56case NVPTX::LD_i32:57case NVPTX::LD_i64:58case NVPTX::LD_i8:59case NVPTX::LDV_i16_v2:60case NVPTX::LDV_i16_v4:61case NVPTX::LDV_i32_v2:62case NVPTX::LDV_i32_v4:63case NVPTX::LDV_i64_v2:64case NVPTX::LDV_i64_v4:65case NVPTX::LDV_i8_v2:66case NVPTX::LDV_i8_v4: {67LoadInsts.push_back(&U);68return true;69}70case NVPTX::cvta_local:71case NVPTX::cvta_local_64:72case NVPTX::cvta_to_local:73case NVPTX::cvta_to_local_64: {74for (auto &U2 : MRI.use_instructions(U.operands_begin()->getReg()))75if (!traverseMoveUse(U2, MRI, RemoveList, LoadInsts))76return false;7778RemoveList.push_back(&U);79return true;80}81default:82return false;83}84}8586static bool eliminateMove(MachineInstr &Mov, const MachineRegisterInfo &MRI,87SmallVectorImpl<MachineInstr *> &RemoveList) {88SmallVector<MachineInstr *, 16> MaybeRemoveList;89SmallVector<MachineInstr *, 16> LoadInsts;9091for (auto &U : MRI.use_instructions(Mov.operands_begin()->getReg()))92if (!traverseMoveUse(U, MRI, MaybeRemoveList, LoadInsts))93return false;9495RemoveList.append(MaybeRemoveList);96RemoveList.push_back(&Mov);9798const MachineOperand *ParamSymbol = Mov.uses().begin();99assert(ParamSymbol->isSymbol());100101constexpr unsigned LDInstBasePtrOpIdx = 5;102constexpr unsigned LDInstAddrSpaceOpIdx = 2;103for (auto *LI : LoadInsts) {104(LI->uses().begin() + LDInstBasePtrOpIdx)105->ChangeToES(ParamSymbol->getSymbolName());106(LI->uses().begin() + LDInstAddrSpaceOpIdx)107->ChangeToImmediate(NVPTX::AddressSpace::Param);108}109return true;110}111112static bool forwardDeviceParams(MachineFunction &MF) {113const auto &MRI = MF.getRegInfo();114115bool Changed = false;116SmallVector<MachineInstr *, 16> RemoveList;117for (auto &MI : make_early_inc_range(*MF.begin()))118if (MI.getOpcode() == NVPTX::MOV32_PARAM ||119MI.getOpcode() == NVPTX::MOV64_PARAM)120Changed |= eliminateMove(MI, MRI, RemoveList);121122for (auto *MI : RemoveList)123MI->eraseFromParent();124125return Changed;126}127128/// ----------------------------------------------------------------------------129/// Pass (Manager) Boilerplate130/// ----------------------------------------------------------------------------131132namespace {133struct NVPTXForwardParamsPass : public MachineFunctionPass {134static char ID;135NVPTXForwardParamsPass() : MachineFunctionPass(ID) {}136137bool runOnMachineFunction(MachineFunction &MF) override;138139void getAnalysisUsage(AnalysisUsage &AU) const override {140MachineFunctionPass::getAnalysisUsage(AU);141}142};143} // namespace144145char NVPTXForwardParamsPass::ID = 0;146147INITIALIZE_PASS(NVPTXForwardParamsPass, "nvptx-forward-params",148"NVPTX Forward Params", false, false)149150bool NVPTXForwardParamsPass::runOnMachineFunction(MachineFunction &MF) {151return forwardDeviceParams(MF);152}153154MachineFunctionPass *llvm::createNVPTXForwardParamsPass() {155return new NVPTXForwardParamsPass();156}157158159