1239310Sdim//===- NVPTXInstrInfo.cpp - NVPTX Instruction Information -----------------===// 2239310Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6239310Sdim// 7239310Sdim//===----------------------------------------------------------------------===// 8239310Sdim// 9239310Sdim// This file contains the NVPTX implementation of the TargetInstrInfo class. 10239310Sdim// 11239310Sdim//===----------------------------------------------------------------------===// 12239310Sdim 13321369Sdim#include "NVPTXInstrInfo.h" 14239310Sdim#include "NVPTX.h" 15239310Sdim#include "NVPTXTargetMachine.h" 16239310Sdim#include "llvm/ADT/STLExtras.h" 17239310Sdim#include "llvm/CodeGen/MachineFunction.h" 18239310Sdim#include "llvm/CodeGen/MachineInstrBuilder.h" 19239310Sdim#include "llvm/CodeGen/MachineRegisterInfo.h" 20280031Sdim#include "llvm/IR/Function.h" 21239310Sdim 22239310Sdimusing namespace llvm; 23239310Sdim 24276479Sdim#define GET_INSTRINFO_CTOR_DTOR 25276479Sdim#include "NVPTXGenInstrInfo.inc" 26276479Sdim 27261991Sdim// Pin the vtable to this file. 28261991Sdimvoid NVPTXInstrInfo::anchor() {} 29261991Sdim 30288943SdimNVPTXInstrInfo::NVPTXInstrInfo() : NVPTXGenInstrInfo(), RegInfo() {} 31239310Sdim 32309124Sdimvoid NVPTXInstrInfo::copyPhysReg(MachineBasicBlock &MBB, 33309124Sdim MachineBasicBlock::iterator I, 34360784Sdim const DebugLoc &DL, MCRegister DestReg, 35360784Sdim MCRegister SrcReg, bool KillSrc) const { 36261991Sdim const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo(); 37261991Sdim const TargetRegisterClass *DestRC = MRI.getRegClass(DestReg); 38261991Sdim const TargetRegisterClass *SrcRC = MRI.getRegClass(SrcReg); 39261991Sdim 40321369Sdim if (RegInfo.getRegSizeInBits(*DestRC) != RegInfo.getRegSizeInBits(*SrcRC)) 41296417Sdim report_fatal_error("Copy one register into another with a different width"); 42261991Sdim 43296417Sdim unsigned Op; 44296417Sdim if (DestRC == &NVPTX::Int1RegsRegClass) { 45296417Sdim Op = NVPTX::IMOV1rr; 46296417Sdim } else if (DestRC == &NVPTX::Int16RegsRegClass) { 47296417Sdim Op = NVPTX::IMOV16rr; 48296417Sdim } else if (DestRC == &NVPTX::Int32RegsRegClass) { 49296417Sdim Op = (SrcRC == &NVPTX::Int32RegsRegClass ? NVPTX::IMOV32rr 50296417Sdim : NVPTX::BITCONVERT_32_F2I); 51296417Sdim } else if (DestRC == &NVPTX::Int64RegsRegClass) { 52296417Sdim Op = (SrcRC == &NVPTX::Int64RegsRegClass ? NVPTX::IMOV64rr 53296417Sdim : NVPTX::BITCONVERT_64_F2I); 54321369Sdim } else if (DestRC == &NVPTX::Float16RegsRegClass) { 55321369Sdim Op = (SrcRC == &NVPTX::Float16RegsRegClass ? NVPTX::FMOV16rr 56321369Sdim : NVPTX::BITCONVERT_16_I2F); 57321369Sdim } else if (DestRC == &NVPTX::Float16x2RegsRegClass) { 58321369Sdim Op = NVPTX::IMOV32rr; 59296417Sdim } else if (DestRC == &NVPTX::Float32RegsRegClass) { 60296417Sdim Op = (SrcRC == &NVPTX::Float32RegsRegClass ? NVPTX::FMOV32rr 61296417Sdim : NVPTX::BITCONVERT_32_I2F); 62296417Sdim } else if (DestRC == &NVPTX::Float64RegsRegClass) { 63296417Sdim Op = (SrcRC == &NVPTX::Float64RegsRegClass ? NVPTX::FMOV64rr 64296417Sdim : NVPTX::BITCONVERT_64_I2F); 65296417Sdim } else { 66261991Sdim llvm_unreachable("Bad register copy"); 67239310Sdim } 68296417Sdim BuildMI(MBB, I, DL, get(Op), DestReg) 69296417Sdim .addReg(SrcReg, getKillRegState(KillSrc)); 70239310Sdim} 71239310Sdim 72239310Sdim/// AnalyzeBranch - Analyze the branching code at the end of MBB, returning 73239310Sdim/// true if it cannot be understood (e.g. it's a switch dispatch or isn't 74239310Sdim/// implemented for a target). Upon success, this returns false and returns 75239310Sdim/// with the following information in various cases: 76239310Sdim/// 77239310Sdim/// 1. If this block ends with no branches (it just falls through to its succ) 78239310Sdim/// just return false, leaving TBB/FBB null. 79239310Sdim/// 2. If this block ends with only an unconditional branch, it sets TBB to be 80239310Sdim/// the destination block. 81239310Sdim/// 3. If this block ends with an conditional branch and it falls through to 82239310Sdim/// an successor block, it sets TBB to be the branch destination block and a 83239310Sdim/// list of operands that evaluate the condition. These 84239310Sdim/// operands can be passed to other TargetInstrInfo methods to create new 85239310Sdim/// branches. 86239310Sdim/// 4. If this block ends with an conditional branch and an unconditional 87239310Sdim/// block, it returns the 'true' destination in TBB, the 'false' destination 88239310Sdim/// in FBB, and a list of operands that evaluate the condition. These 89239310Sdim/// operands can be passed to other TargetInstrInfo methods to create new 90239310Sdim/// branches. 91239310Sdim/// 92314564Sdim/// Note that removeBranch and insertBranch must be implemented to support 93239310Sdim/// cases where this method returns success. 94239310Sdim/// 95309124Sdimbool NVPTXInstrInfo::analyzeBranch(MachineBasicBlock &MBB, 96309124Sdim MachineBasicBlock *&TBB, 97309124Sdim MachineBasicBlock *&FBB, 98309124Sdim SmallVectorImpl<MachineOperand> &Cond, 99309124Sdim bool AllowModify) const { 100239310Sdim // If the block has no terminators, it just falls into the block after it. 101239310Sdim MachineBasicBlock::iterator I = MBB.end(); 102309124Sdim if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) 103239310Sdim return false; 104239310Sdim 105239310Sdim // Get the last instruction in the block. 106309124Sdim MachineInstr &LastInst = *I; 107239310Sdim 108239310Sdim // If there is only one terminator instruction, process it. 109309124Sdim if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) { 110309124Sdim if (LastInst.getOpcode() == NVPTX::GOTO) { 111309124Sdim TBB = LastInst.getOperand(0).getMBB(); 112239310Sdim return false; 113309124Sdim } else if (LastInst.getOpcode() == NVPTX::CBranch) { 114239310Sdim // Block ends with fall-through condbranch. 115309124Sdim TBB = LastInst.getOperand(1).getMBB(); 116309124Sdim Cond.push_back(LastInst.getOperand(0)); 117239310Sdim return false; 118239310Sdim } 119239310Sdim // Otherwise, don't know what this is. 120239310Sdim return true; 121239310Sdim } 122239310Sdim 123239310Sdim // Get the instruction before it if it's a terminator. 124309124Sdim MachineInstr &SecondLastInst = *I; 125239310Sdim 126239310Sdim // If there are three terminators, we don't know what sort of block this is. 127309124Sdim if (I != MBB.begin() && isUnpredicatedTerminator(*--I)) 128239310Sdim return true; 129239310Sdim 130239310Sdim // If the block ends with NVPTX::GOTO and NVPTX:CBranch, handle it. 131309124Sdim if (SecondLastInst.getOpcode() == NVPTX::CBranch && 132309124Sdim LastInst.getOpcode() == NVPTX::GOTO) { 133309124Sdim TBB = SecondLastInst.getOperand(1).getMBB(); 134309124Sdim Cond.push_back(SecondLastInst.getOperand(0)); 135309124Sdim FBB = LastInst.getOperand(0).getMBB(); 136239310Sdim return false; 137239310Sdim } 138239310Sdim 139239310Sdim // If the block ends with two NVPTX:GOTOs, handle it. The second one is not 140239310Sdim // executed, so remove it. 141309124Sdim if (SecondLastInst.getOpcode() == NVPTX::GOTO && 142309124Sdim LastInst.getOpcode() == NVPTX::GOTO) { 143309124Sdim TBB = SecondLastInst.getOperand(0).getMBB(); 144239310Sdim I = LastInst; 145239310Sdim if (AllowModify) 146239310Sdim I->eraseFromParent(); 147239310Sdim return false; 148239310Sdim } 149239310Sdim 150239310Sdim // Otherwise, can't handle this. 151239310Sdim return true; 152239310Sdim} 153239310Sdim 154314564Sdimunsigned NVPTXInstrInfo::removeBranch(MachineBasicBlock &MBB, 155314564Sdim int *BytesRemoved) const { 156314564Sdim assert(!BytesRemoved && "code size not handled"); 157239310Sdim MachineBasicBlock::iterator I = MBB.end(); 158249423Sdim if (I == MBB.begin()) 159249423Sdim return 0; 160239310Sdim --I; 161239310Sdim if (I->getOpcode() != NVPTX::GOTO && I->getOpcode() != NVPTX::CBranch) 162239310Sdim return 0; 163239310Sdim 164239310Sdim // Remove the branch. 165239310Sdim I->eraseFromParent(); 166239310Sdim 167239310Sdim I = MBB.end(); 168239310Sdim 169249423Sdim if (I == MBB.begin()) 170249423Sdim return 1; 171239310Sdim --I; 172239310Sdim if (I->getOpcode() != NVPTX::CBranch) 173239310Sdim return 1; 174239310Sdim 175239310Sdim // Remove the branch. 176239310Sdim I->eraseFromParent(); 177239310Sdim return 2; 178239310Sdim} 179239310Sdim 180314564Sdimunsigned NVPTXInstrInfo::insertBranch(MachineBasicBlock &MBB, 181309124Sdim MachineBasicBlock *TBB, 182309124Sdim MachineBasicBlock *FBB, 183309124Sdim ArrayRef<MachineOperand> Cond, 184314564Sdim const DebugLoc &DL, 185314564Sdim int *BytesAdded) const { 186314564Sdim assert(!BytesAdded && "code size not handled"); 187314564Sdim 188239310Sdim // Shouldn't be a fall through. 189314564Sdim assert(TBB && "insertBranch must not be told to insert a fallthrough"); 190239310Sdim assert((Cond.size() == 1 || Cond.size() == 0) && 191239310Sdim "NVPTX branch conditions have two components!"); 192239310Sdim 193239310Sdim // One-way branch. 194276479Sdim if (!FBB) { 195249423Sdim if (Cond.empty()) // Unconditional branch 196239310Sdim BuildMI(&MBB, DL, get(NVPTX::GOTO)).addMBB(TBB); 197249423Sdim else // Conditional branch 198249423Sdim BuildMI(&MBB, DL, get(NVPTX::CBranch)).addReg(Cond[0].getReg()) 199249423Sdim .addMBB(TBB); 200239310Sdim return 1; 201239310Sdim } 202239310Sdim 203239310Sdim // Two-way Conditional Branch. 204249423Sdim BuildMI(&MBB, DL, get(NVPTX::CBranch)).addReg(Cond[0].getReg()).addMBB(TBB); 205239310Sdim BuildMI(&MBB, DL, get(NVPTX::GOTO)).addMBB(FBB); 206239310Sdim return 2; 207239310Sdim} 208