196 lines · cpp
1//===- NVPTXInstrInfo.cpp - NVPTX Instruction Information -----------------===//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// This file contains the NVPTX implementation of the TargetInstrInfo class.10//11//===----------------------------------------------------------------------===//12 13#include "NVPTXInstrInfo.h"14#include "NVPTX.h"15#include "NVPTXSubtarget.h"16#include "llvm/CodeGen/MachineFunction.h"17#include "llvm/CodeGen/MachineInstrBuilder.h"18#include "llvm/CodeGen/MachineRegisterInfo.h"19 20using namespace llvm;21 22#define GET_INSTRINFO_CTOR_DTOR23#include "NVPTXGenInstrInfo.inc"24 25// Pin the vtable to this file.26void NVPTXInstrInfo::anchor() {}27 28NVPTXInstrInfo::NVPTXInstrInfo(const NVPTXSubtarget &STI)29 : NVPTXGenInstrInfo(STI, RegInfo), RegInfo() {}30 31void NVPTXInstrInfo::copyPhysReg(MachineBasicBlock &MBB,32 MachineBasicBlock::iterator I,33 const DebugLoc &DL, Register DestReg,34 Register SrcReg, bool KillSrc,35 bool RenamableDest, bool RenamableSrc) const {36 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();37 const TargetRegisterClass *DestRC = MRI.getRegClass(DestReg);38 const TargetRegisterClass *SrcRC = MRI.getRegClass(SrcReg);39 40 if (DestRC != SrcRC)41 report_fatal_error("Copy one register into another with a different width");42 43 unsigned Op;44 if (DestRC == &NVPTX::B1RegClass)45 Op = NVPTX::MOV_B1_r;46 else if (DestRC == &NVPTX::B16RegClass)47 Op = NVPTX::MOV_B16_r;48 else if (DestRC == &NVPTX::B32RegClass)49 Op = NVPTX::MOV_B32_r;50 else if (DestRC == &NVPTX::B64RegClass)51 Op = NVPTX::MOV_B64_r;52 else if (DestRC == &NVPTX::B128RegClass)53 Op = NVPTX::MOV_B128_r;54 else55 llvm_unreachable("Bad register copy");56 57 BuildMI(MBB, I, DL, get(Op), DestReg)58 .addReg(SrcReg, getKillRegState(KillSrc));59}60 61/// analyzeBranch - Analyze the branching code at the end of MBB, returning62/// true if it cannot be understood (e.g. it's a switch dispatch or isn't63/// implemented for a target). Upon success, this returns false and returns64/// with the following information in various cases:65///66/// 1. If this block ends with no branches (it just falls through to its succ)67/// just return false, leaving TBB/FBB null.68/// 2. If this block ends with only an unconditional branch, it sets TBB to be69/// the destination block.70/// 3. If this block ends with an conditional branch and it falls through to71/// an successor block, it sets TBB to be the branch destination block and a72/// list of operands that evaluate the condition. These73/// operands can be passed to other TargetInstrInfo methods to create new74/// branches.75/// 4. If this block ends with an conditional branch and an unconditional76/// block, it returns the 'true' destination in TBB, the 'false' destination77/// in FBB, and a list of operands that evaluate the condition. These78/// operands can be passed to other TargetInstrInfo methods to create new79/// branches.80///81/// Note that removeBranch and insertBranch must be implemented to support82/// cases where this method returns success.83///84bool NVPTXInstrInfo::analyzeBranch(MachineBasicBlock &MBB,85 MachineBasicBlock *&TBB,86 MachineBasicBlock *&FBB,87 SmallVectorImpl<MachineOperand> &Cond,88 bool AllowModify) const {89 // If the block has no terminators, it just falls into the block after it.90 MachineBasicBlock::iterator I = MBB.end();91 if (I == MBB.begin() || !isUnpredicatedTerminator(*--I))92 return false;93 94 // Get the last instruction in the block.95 MachineInstr &LastInst = *I;96 97 // If there is only one terminator instruction, process it.98 if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {99 if (LastInst.getOpcode() == NVPTX::GOTO) {100 TBB = LastInst.getOperand(0).getMBB();101 return false;102 } else if (LastInst.getOpcode() == NVPTX::CBranch) {103 // Block ends with fall-through condbranch.104 TBB = LastInst.getOperand(1).getMBB();105 Cond.push_back(LastInst.getOperand(0));106 return false;107 }108 // Otherwise, don't know what this is.109 return true;110 }111 112 // Get the instruction before it if it's a terminator.113 MachineInstr &SecondLastInst = *I;114 115 // If there are three terminators, we don't know what sort of block this is.116 if (I != MBB.begin() && isUnpredicatedTerminator(*--I))117 return true;118 119 // If the block ends with NVPTX::GOTO and NVPTX:CBranch, handle it.120 if (SecondLastInst.getOpcode() == NVPTX::CBranch &&121 LastInst.getOpcode() == NVPTX::GOTO) {122 TBB = SecondLastInst.getOperand(1).getMBB();123 Cond.push_back(SecondLastInst.getOperand(0));124 FBB = LastInst.getOperand(0).getMBB();125 return false;126 }127 128 // If the block ends with two NVPTX:GOTOs, handle it. The second one is not129 // executed, so remove it.130 if (SecondLastInst.getOpcode() == NVPTX::GOTO &&131 LastInst.getOpcode() == NVPTX::GOTO) {132 TBB = SecondLastInst.getOperand(0).getMBB();133 I = LastInst;134 if (AllowModify)135 I->eraseFromParent();136 return false;137 }138 139 // Otherwise, can't handle this.140 return true;141}142 143unsigned NVPTXInstrInfo::removeBranch(MachineBasicBlock &MBB,144 int *BytesRemoved) const {145 assert(!BytesRemoved && "code size not handled");146 MachineBasicBlock::iterator I = MBB.end();147 if (I == MBB.begin())148 return 0;149 --I;150 if (I->getOpcode() != NVPTX::GOTO && I->getOpcode() != NVPTX::CBranch)151 return 0;152 153 // Remove the branch.154 I->eraseFromParent();155 156 I = MBB.end();157 158 if (I == MBB.begin())159 return 1;160 --I;161 if (I->getOpcode() != NVPTX::CBranch)162 return 1;163 164 // Remove the branch.165 I->eraseFromParent();166 return 2;167}168 169unsigned NVPTXInstrInfo::insertBranch(MachineBasicBlock &MBB,170 MachineBasicBlock *TBB,171 MachineBasicBlock *FBB,172 ArrayRef<MachineOperand> Cond,173 const DebugLoc &DL,174 int *BytesAdded) const {175 assert(!BytesAdded && "code size not handled");176 177 // Shouldn't be a fall through.178 assert(TBB && "insertBranch must not be told to insert a fallthrough");179 assert((Cond.size() == 1 || Cond.size() == 0) &&180 "NVPTX branch conditions have two components!");181 182 // One-way branch.183 if (!FBB) {184 if (Cond.empty()) // Unconditional branch185 BuildMI(&MBB, DL, get(NVPTX::GOTO)).addMBB(TBB);186 else // Conditional branch187 BuildMI(&MBB, DL, get(NVPTX::CBranch)).add(Cond[0]).addMBB(TBB);188 return 1;189 }190 191 // Two-way Conditional Branch.192 BuildMI(&MBB, DL, get(NVPTX::CBranch)).add(Cond[0]).addMBB(TBB);193 BuildMI(&MBB, DL, get(NVPTX::GOTO)).addMBB(FBB);194 return 2;195}196