10b57cec5SDimitry Andric //===- NVPTXInstrInfo.cpp - NVPTX Instruction Information -----------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file contains the NVPTX implementation of the TargetInstrInfo class. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "NVPTXInstrInfo.h" 140b57cec5SDimitry Andric #include "NVPTX.h" 150b57cec5SDimitry Andric #include "NVPTXTargetMachine.h" 160b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 170b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 200b57cec5SDimitry Andric #include "llvm/IR/Function.h" 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric using namespace llvm; 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric #define GET_INSTRINFO_CTOR_DTOR 250b57cec5SDimitry Andric #include "NVPTXGenInstrInfo.inc" 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric // Pin the vtable to this file. 280b57cec5SDimitry Andric void NVPTXInstrInfo::anchor() {} 290b57cec5SDimitry Andric 3081ad6265SDimitry Andric NVPTXInstrInfo::NVPTXInstrInfo() : RegInfo() {} 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric void NVPTXInstrInfo::copyPhysReg(MachineBasicBlock &MBB, 330b57cec5SDimitry Andric MachineBasicBlock::iterator I, 34480093f4SDimitry Andric const DebugLoc &DL, MCRegister DestReg, 35480093f4SDimitry Andric MCRegister SrcReg, bool KillSrc) const { 360b57cec5SDimitry Andric const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo(); 370b57cec5SDimitry Andric const TargetRegisterClass *DestRC = MRI.getRegClass(DestReg); 380b57cec5SDimitry Andric const TargetRegisterClass *SrcRC = MRI.getRegClass(SrcReg); 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric if (RegInfo.getRegSizeInBits(*DestRC) != RegInfo.getRegSizeInBits(*SrcRC)) 410b57cec5SDimitry Andric report_fatal_error("Copy one register into another with a different width"); 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric unsigned Op; 440b57cec5SDimitry Andric if (DestRC == &NVPTX::Int1RegsRegClass) { 450b57cec5SDimitry Andric Op = NVPTX::IMOV1rr; 460b57cec5SDimitry Andric } else if (DestRC == &NVPTX::Int16RegsRegClass) { 470b57cec5SDimitry Andric Op = NVPTX::IMOV16rr; 480b57cec5SDimitry Andric } else if (DestRC == &NVPTX::Int32RegsRegClass) { 490b57cec5SDimitry Andric Op = (SrcRC == &NVPTX::Int32RegsRegClass ? NVPTX::IMOV32rr 500b57cec5SDimitry Andric : NVPTX::BITCONVERT_32_F2I); 510b57cec5SDimitry Andric } else if (DestRC == &NVPTX::Int64RegsRegClass) { 520b57cec5SDimitry Andric Op = (SrcRC == &NVPTX::Int64RegsRegClass ? NVPTX::IMOV64rr 530b57cec5SDimitry Andric : NVPTX::BITCONVERT_64_F2I); 54*0fca6ea1SDimitry Andric } else if (DestRC == &NVPTX::Int128RegsRegClass) { 55*0fca6ea1SDimitry Andric Op = NVPTX::IMOV128rr; 560b57cec5SDimitry Andric } else if (DestRC == &NVPTX::Float32RegsRegClass) { 570b57cec5SDimitry Andric Op = (SrcRC == &NVPTX::Float32RegsRegClass ? NVPTX::FMOV32rr 580b57cec5SDimitry Andric : NVPTX::BITCONVERT_32_I2F); 590b57cec5SDimitry Andric } else if (DestRC == &NVPTX::Float64RegsRegClass) { 600b57cec5SDimitry Andric Op = (SrcRC == &NVPTX::Float64RegsRegClass ? NVPTX::FMOV64rr 610b57cec5SDimitry Andric : NVPTX::BITCONVERT_64_I2F); 620b57cec5SDimitry Andric } else { 630b57cec5SDimitry Andric llvm_unreachable("Bad register copy"); 640b57cec5SDimitry Andric } 650b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(Op), DestReg) 660b57cec5SDimitry Andric .addReg(SrcReg, getKillRegState(KillSrc)); 670b57cec5SDimitry Andric } 680b57cec5SDimitry Andric 695ffd83dbSDimitry Andric /// analyzeBranch - Analyze the branching code at the end of MBB, returning 700b57cec5SDimitry Andric /// true if it cannot be understood (e.g. it's a switch dispatch or isn't 710b57cec5SDimitry Andric /// implemented for a target). Upon success, this returns false and returns 720b57cec5SDimitry Andric /// with the following information in various cases: 730b57cec5SDimitry Andric /// 740b57cec5SDimitry Andric /// 1. If this block ends with no branches (it just falls through to its succ) 750b57cec5SDimitry Andric /// just return false, leaving TBB/FBB null. 760b57cec5SDimitry Andric /// 2. If this block ends with only an unconditional branch, it sets TBB to be 770b57cec5SDimitry Andric /// the destination block. 780b57cec5SDimitry Andric /// 3. If this block ends with an conditional branch and it falls through to 790b57cec5SDimitry Andric /// an successor block, it sets TBB to be the branch destination block and a 800b57cec5SDimitry Andric /// list of operands that evaluate the condition. These 810b57cec5SDimitry Andric /// operands can be passed to other TargetInstrInfo methods to create new 820b57cec5SDimitry Andric /// branches. 830b57cec5SDimitry Andric /// 4. If this block ends with an conditional branch and an unconditional 840b57cec5SDimitry Andric /// block, it returns the 'true' destination in TBB, the 'false' destination 850b57cec5SDimitry Andric /// in FBB, and a list of operands that evaluate the condition. These 860b57cec5SDimitry Andric /// operands can be passed to other TargetInstrInfo methods to create new 870b57cec5SDimitry Andric /// branches. 880b57cec5SDimitry Andric /// 890b57cec5SDimitry Andric /// Note that removeBranch and insertBranch must be implemented to support 900b57cec5SDimitry Andric /// cases where this method returns success. 910b57cec5SDimitry Andric /// 920b57cec5SDimitry Andric bool NVPTXInstrInfo::analyzeBranch(MachineBasicBlock &MBB, 930b57cec5SDimitry Andric MachineBasicBlock *&TBB, 940b57cec5SDimitry Andric MachineBasicBlock *&FBB, 950b57cec5SDimitry Andric SmallVectorImpl<MachineOperand> &Cond, 960b57cec5SDimitry Andric bool AllowModify) const { 970b57cec5SDimitry Andric // If the block has no terminators, it just falls into the block after it. 980b57cec5SDimitry Andric MachineBasicBlock::iterator I = MBB.end(); 990b57cec5SDimitry Andric if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) 1000b57cec5SDimitry Andric return false; 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric // Get the last instruction in the block. 1030b57cec5SDimitry Andric MachineInstr &LastInst = *I; 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric // If there is only one terminator instruction, process it. 1060b57cec5SDimitry Andric if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) { 1070b57cec5SDimitry Andric if (LastInst.getOpcode() == NVPTX::GOTO) { 1080b57cec5SDimitry Andric TBB = LastInst.getOperand(0).getMBB(); 1090b57cec5SDimitry Andric return false; 1100b57cec5SDimitry Andric } else if (LastInst.getOpcode() == NVPTX::CBranch) { 1110b57cec5SDimitry Andric // Block ends with fall-through condbranch. 1120b57cec5SDimitry Andric TBB = LastInst.getOperand(1).getMBB(); 1130b57cec5SDimitry Andric Cond.push_back(LastInst.getOperand(0)); 1140b57cec5SDimitry Andric return false; 1150b57cec5SDimitry Andric } 1160b57cec5SDimitry Andric // Otherwise, don't know what this is. 1170b57cec5SDimitry Andric return true; 1180b57cec5SDimitry Andric } 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric // Get the instruction before it if it's a terminator. 1210b57cec5SDimitry Andric MachineInstr &SecondLastInst = *I; 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric // If there are three terminators, we don't know what sort of block this is. 1240b57cec5SDimitry Andric if (I != MBB.begin() && isUnpredicatedTerminator(*--I)) 1250b57cec5SDimitry Andric return true; 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric // If the block ends with NVPTX::GOTO and NVPTX:CBranch, handle it. 1280b57cec5SDimitry Andric if (SecondLastInst.getOpcode() == NVPTX::CBranch && 1290b57cec5SDimitry Andric LastInst.getOpcode() == NVPTX::GOTO) { 1300b57cec5SDimitry Andric TBB = SecondLastInst.getOperand(1).getMBB(); 1310b57cec5SDimitry Andric Cond.push_back(SecondLastInst.getOperand(0)); 1320b57cec5SDimitry Andric FBB = LastInst.getOperand(0).getMBB(); 1330b57cec5SDimitry Andric return false; 1340b57cec5SDimitry Andric } 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric // If the block ends with two NVPTX:GOTOs, handle it. The second one is not 1370b57cec5SDimitry Andric // executed, so remove it. 1380b57cec5SDimitry Andric if (SecondLastInst.getOpcode() == NVPTX::GOTO && 1390b57cec5SDimitry Andric LastInst.getOpcode() == NVPTX::GOTO) { 1400b57cec5SDimitry Andric TBB = SecondLastInst.getOperand(0).getMBB(); 1410b57cec5SDimitry Andric I = LastInst; 1420b57cec5SDimitry Andric if (AllowModify) 1430b57cec5SDimitry Andric I->eraseFromParent(); 1440b57cec5SDimitry Andric return false; 1450b57cec5SDimitry Andric } 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric // Otherwise, can't handle this. 1480b57cec5SDimitry Andric return true; 1490b57cec5SDimitry Andric } 1500b57cec5SDimitry Andric 1510b57cec5SDimitry Andric unsigned NVPTXInstrInfo::removeBranch(MachineBasicBlock &MBB, 1520b57cec5SDimitry Andric int *BytesRemoved) const { 1530b57cec5SDimitry Andric assert(!BytesRemoved && "code size not handled"); 1540b57cec5SDimitry Andric MachineBasicBlock::iterator I = MBB.end(); 1550b57cec5SDimitry Andric if (I == MBB.begin()) 1560b57cec5SDimitry Andric return 0; 1570b57cec5SDimitry Andric --I; 1580b57cec5SDimitry Andric if (I->getOpcode() != NVPTX::GOTO && I->getOpcode() != NVPTX::CBranch) 1590b57cec5SDimitry Andric return 0; 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric // Remove the branch. 1620b57cec5SDimitry Andric I->eraseFromParent(); 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric I = MBB.end(); 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andric if (I == MBB.begin()) 1670b57cec5SDimitry Andric return 1; 1680b57cec5SDimitry Andric --I; 1690b57cec5SDimitry Andric if (I->getOpcode() != NVPTX::CBranch) 1700b57cec5SDimitry Andric return 1; 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric // Remove the branch. 1730b57cec5SDimitry Andric I->eraseFromParent(); 1740b57cec5SDimitry Andric return 2; 1750b57cec5SDimitry Andric } 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric unsigned NVPTXInstrInfo::insertBranch(MachineBasicBlock &MBB, 1780b57cec5SDimitry Andric MachineBasicBlock *TBB, 1790b57cec5SDimitry Andric MachineBasicBlock *FBB, 1800b57cec5SDimitry Andric ArrayRef<MachineOperand> Cond, 1810b57cec5SDimitry Andric const DebugLoc &DL, 1820b57cec5SDimitry Andric int *BytesAdded) const { 1830b57cec5SDimitry Andric assert(!BytesAdded && "code size not handled"); 1840b57cec5SDimitry Andric 1850b57cec5SDimitry Andric // Shouldn't be a fall through. 1860b57cec5SDimitry Andric assert(TBB && "insertBranch must not be told to insert a fallthrough"); 1870b57cec5SDimitry Andric assert((Cond.size() == 1 || Cond.size() == 0) && 1880b57cec5SDimitry Andric "NVPTX branch conditions have two components!"); 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric // One-way branch. 1910b57cec5SDimitry Andric if (!FBB) { 1920b57cec5SDimitry Andric if (Cond.empty()) // Unconditional branch 1930b57cec5SDimitry Andric BuildMI(&MBB, DL, get(NVPTX::GOTO)).addMBB(TBB); 1940b57cec5SDimitry Andric else // Conditional branch 195349cc55cSDimitry Andric BuildMI(&MBB, DL, get(NVPTX::CBranch)).add(Cond[0]).addMBB(TBB); 1960b57cec5SDimitry Andric return 1; 1970b57cec5SDimitry Andric } 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric // Two-way Conditional Branch. 200349cc55cSDimitry Andric BuildMI(&MBB, DL, get(NVPTX::CBranch)).add(Cond[0]).addMBB(TBB); 2010b57cec5SDimitry Andric BuildMI(&MBB, DL, get(NVPTX::GOTO)).addMBB(FBB); 2020b57cec5SDimitry Andric return 2; 2030b57cec5SDimitry Andric } 204