xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/NVPTX/NVPTXInstrInfo.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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