162 lines · cpp
1//===-- NVPTXPeephole.cpp - NVPTX Peephole Optimiztions -------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// In NVPTX, NVPTXFrameLowering will emit following instruction at the beginning10// of a MachineFunction.11//12// mov %SPL, %depot13// cvta.local %SP, %SPL14//15// Because Frame Index is a generic address and alloca can only return generic16// pointer, without this pass the instructions producing alloca'ed address will17// be based on %SP. NVPTXLowerAlloca tends to help replace store and load on18// this address with their .local versions, but this may introduce a lot of19// cvta.to.local instructions. Performance can be improved if we avoid casting20// address back and forth and directly calculate local address based on %SPL.21// This peephole pass optimizes these cases, for example22//23// It will transform the following pattern24// %0 = LEA_ADDRi64 %VRFrame64, 425// %1 = cvta_to_local_64 %026//27// into28// %1 = LEA_ADDRi64 %VRFrameLocal64, 429//30// %VRFrameLocal64 is the virtual register name of %SPL31//32//===----------------------------------------------------------------------===//33 34#include "NVPTX.h"35#include "NVPTXRegisterInfo.h"36#include "NVPTXSubtarget.h"37#include "llvm/CodeGen/MachineFunctionPass.h"38#include "llvm/CodeGen/MachineInstrBuilder.h"39#include "llvm/CodeGen/MachineRegisterInfo.h"40#include "llvm/CodeGen/TargetInstrInfo.h"41#include "llvm/CodeGen/TargetRegisterInfo.h"42 43using namespace llvm;44 45#define DEBUG_TYPE "nvptx-peephole"46 47namespace {48struct NVPTXPeephole : public MachineFunctionPass {49 public:50 static char ID;51 NVPTXPeephole() : MachineFunctionPass(ID) {}52 53 bool runOnMachineFunction(MachineFunction &MF) override;54 55 StringRef getPassName() const override {56 return "NVPTX optimize redundant cvta.to.local instruction";57 }58 59 void getAnalysisUsage(AnalysisUsage &AU) const override {60 MachineFunctionPass::getAnalysisUsage(AU);61 }62};63}64 65char NVPTXPeephole::ID = 0;66 67INITIALIZE_PASS(NVPTXPeephole, "nvptx-peephole", "NVPTX Peephole", false, false)68 69static bool isCVTAToLocalCombinationCandidate(MachineInstr &Root) {70 auto &MBB = *Root.getParent();71 auto &MF = *MBB.getParent();72 // Check current instruction is cvta.to.local73 if (Root.getOpcode() != NVPTX::cvta_to_local_64 &&74 Root.getOpcode() != NVPTX::cvta_to_local)75 return false;76 77 auto &Op = Root.getOperand(1);78 const auto &MRI = MF.getRegInfo();79 MachineInstr *GenericAddrDef = nullptr;80 if (Op.isReg() && Op.getReg().isVirtual()) {81 GenericAddrDef = MRI.getUniqueVRegDef(Op.getReg());82 }83 84 // Check the register operand is uniquely defined by LEA_ADDRi instruction85 if (!GenericAddrDef || GenericAddrDef->getParent() != &MBB ||86 (GenericAddrDef->getOpcode() != NVPTX::LEA_ADDRi64 &&87 GenericAddrDef->getOpcode() != NVPTX::LEA_ADDRi)) {88 return false;89 }90 91 const NVPTXRegisterInfo *NRI =92 MF.getSubtarget<NVPTXSubtarget>().getRegisterInfo();93 94 // Check the LEA_ADDRi operand is Frame index95 auto &BaseAddrOp = GenericAddrDef->getOperand(1);96 if (BaseAddrOp.isReg() && BaseAddrOp.getReg() == NRI->getFrameRegister(MF)) {97 return true;98 }99 100 return false;101}102 103static void CombineCVTAToLocal(MachineInstr &Root) {104 auto &MBB = *Root.getParent();105 auto &MF = *MBB.getParent();106 const auto &MRI = MF.getRegInfo();107 const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();108 auto &Prev = *MRI.getUniqueVRegDef(Root.getOperand(1).getReg());109 110 const NVPTXRegisterInfo *NRI =111 MF.getSubtarget<NVPTXSubtarget>().getRegisterInfo();112 113 MachineInstrBuilder MIB =114 BuildMI(MF, Root.getDebugLoc(), TII->get(Prev.getOpcode()),115 Root.getOperand(0).getReg())116 .addReg(NRI->getFrameLocalRegister(MF))117 .add(Prev.getOperand(2));118 119 MBB.insert((MachineBasicBlock::iterator)&Root, MIB);120 121 // Check if MRI has only one non dbg use, which is Root122 if (MRI.hasOneNonDBGUse(Prev.getOperand(0).getReg())) {123 Prev.eraseFromParent();124 }125 Root.eraseFromParent();126}127 128bool NVPTXPeephole::runOnMachineFunction(MachineFunction &MF) {129 if (skipFunction(MF.getFunction()))130 return false;131 132 bool Changed = false;133 // Loop over all of the basic blocks.134 for (auto &MBB : MF) {135 // Traverse the basic block.136 auto BlockIter = MBB.begin();137 138 while (BlockIter != MBB.end()) {139 auto &MI = *BlockIter++;140 if (isCVTAToLocalCombinationCandidate(MI)) {141 CombineCVTAToLocal(MI);142 Changed = true;143 }144 } // Instruction145 } // Basic Block146 147 const NVPTXRegisterInfo *NRI =148 MF.getSubtarget<NVPTXSubtarget>().getRegisterInfo();149 150 // Remove unnecessary %VRFrame = cvta.local %VRFrameLocal151 const auto &MRI = MF.getRegInfo();152 if (MRI.use_empty(NRI->getFrameRegister(MF))) {153 if (auto MI = MRI.getUniqueVRegDef(NRI->getFrameRegister(MF))) {154 MI->eraseFromParent();155 }156 }157 158 return Changed;159}160 161MachineFunctionPass *llvm::createNVPTXPeephole() { return new NVPTXPeephole(); }162