109467b48Spatrick //===- NVPTXInstrInfo.cpp - NVPTX Instruction Information -----------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This file contains the NVPTX implementation of the TargetInstrInfo class.
1009467b48Spatrick //
1109467b48Spatrick //===----------------------------------------------------------------------===//
1209467b48Spatrick
1309467b48Spatrick #include "NVPTXInstrInfo.h"
1409467b48Spatrick #include "NVPTX.h"
1509467b48Spatrick #include "NVPTXTargetMachine.h"
1609467b48Spatrick #include "llvm/ADT/STLExtras.h"
1709467b48Spatrick #include "llvm/CodeGen/MachineFunction.h"
1809467b48Spatrick #include "llvm/CodeGen/MachineInstrBuilder.h"
1909467b48Spatrick #include "llvm/CodeGen/MachineRegisterInfo.h"
2009467b48Spatrick #include "llvm/IR/Function.h"
2109467b48Spatrick
2209467b48Spatrick using namespace llvm;
2309467b48Spatrick
2409467b48Spatrick #define GET_INSTRINFO_CTOR_DTOR
2509467b48Spatrick #include "NVPTXGenInstrInfo.inc"
2609467b48Spatrick
2709467b48Spatrick // Pin the vtable to this file.
anchor()2809467b48Spatrick void NVPTXInstrInfo::anchor() {}
2909467b48Spatrick
NVPTXInstrInfo()30*d415bd75Srobert NVPTXInstrInfo::NVPTXInstrInfo() : RegInfo() {}
3109467b48Spatrick
copyPhysReg(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,const DebugLoc & DL,MCRegister DestReg,MCRegister SrcReg,bool KillSrc) const3209467b48Spatrick void NVPTXInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
3309467b48Spatrick MachineBasicBlock::iterator I,
3409467b48Spatrick const DebugLoc &DL, MCRegister DestReg,
3509467b48Spatrick MCRegister SrcReg, bool KillSrc) const {
3609467b48Spatrick const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3709467b48Spatrick const TargetRegisterClass *DestRC = MRI.getRegClass(DestReg);
3809467b48Spatrick const TargetRegisterClass *SrcRC = MRI.getRegClass(SrcReg);
3909467b48Spatrick
4009467b48Spatrick if (RegInfo.getRegSizeInBits(*DestRC) != RegInfo.getRegSizeInBits(*SrcRC))
4109467b48Spatrick report_fatal_error("Copy one register into another with a different width");
4209467b48Spatrick
4309467b48Spatrick unsigned Op;
4409467b48Spatrick if (DestRC == &NVPTX::Int1RegsRegClass) {
4509467b48Spatrick Op = NVPTX::IMOV1rr;
4609467b48Spatrick } else if (DestRC == &NVPTX::Int16RegsRegClass) {
4709467b48Spatrick Op = NVPTX::IMOV16rr;
4809467b48Spatrick } else if (DestRC == &NVPTX::Int32RegsRegClass) {
4909467b48Spatrick Op = (SrcRC == &NVPTX::Int32RegsRegClass ? NVPTX::IMOV32rr
5009467b48Spatrick : NVPTX::BITCONVERT_32_F2I);
5109467b48Spatrick } else if (DestRC == &NVPTX::Int64RegsRegClass) {
5209467b48Spatrick Op = (SrcRC == &NVPTX::Int64RegsRegClass ? NVPTX::IMOV64rr
5309467b48Spatrick : NVPTX::BITCONVERT_64_F2I);
5409467b48Spatrick } else if (DestRC == &NVPTX::Float16RegsRegClass) {
5509467b48Spatrick Op = (SrcRC == &NVPTX::Float16RegsRegClass ? NVPTX::FMOV16rr
5609467b48Spatrick : NVPTX::BITCONVERT_16_I2F);
5709467b48Spatrick } else if (DestRC == &NVPTX::Float16x2RegsRegClass) {
5809467b48Spatrick Op = NVPTX::IMOV32rr;
5909467b48Spatrick } else if (DestRC == &NVPTX::Float32RegsRegClass) {
6009467b48Spatrick Op = (SrcRC == &NVPTX::Float32RegsRegClass ? NVPTX::FMOV32rr
6109467b48Spatrick : NVPTX::BITCONVERT_32_I2F);
6209467b48Spatrick } else if (DestRC == &NVPTX::Float64RegsRegClass) {
6309467b48Spatrick Op = (SrcRC == &NVPTX::Float64RegsRegClass ? NVPTX::FMOV64rr
6409467b48Spatrick : NVPTX::BITCONVERT_64_I2F);
6509467b48Spatrick } else {
6609467b48Spatrick llvm_unreachable("Bad register copy");
6709467b48Spatrick }
6809467b48Spatrick BuildMI(MBB, I, DL, get(Op), DestReg)
6909467b48Spatrick .addReg(SrcReg, getKillRegState(KillSrc));
7009467b48Spatrick }
7109467b48Spatrick
72097a140dSpatrick /// analyzeBranch - Analyze the branching code at the end of MBB, returning
7309467b48Spatrick /// true if it cannot be understood (e.g. it's a switch dispatch or isn't
7409467b48Spatrick /// implemented for a target). Upon success, this returns false and returns
7509467b48Spatrick /// with the following information in various cases:
7609467b48Spatrick ///
7709467b48Spatrick /// 1. If this block ends with no branches (it just falls through to its succ)
7809467b48Spatrick /// just return false, leaving TBB/FBB null.
7909467b48Spatrick /// 2. If this block ends with only an unconditional branch, it sets TBB to be
8009467b48Spatrick /// the destination block.
8109467b48Spatrick /// 3. If this block ends with an conditional branch and it falls through to
8209467b48Spatrick /// an successor block, it sets TBB to be the branch destination block and a
8309467b48Spatrick /// list of operands that evaluate the condition. These
8409467b48Spatrick /// operands can be passed to other TargetInstrInfo methods to create new
8509467b48Spatrick /// branches.
8609467b48Spatrick /// 4. If this block ends with an conditional branch and an unconditional
8709467b48Spatrick /// block, it returns the 'true' destination in TBB, the 'false' destination
8809467b48Spatrick /// in FBB, and a list of operands that evaluate the condition. These
8909467b48Spatrick /// operands can be passed to other TargetInstrInfo methods to create new
9009467b48Spatrick /// branches.
9109467b48Spatrick ///
9209467b48Spatrick /// Note that removeBranch and insertBranch must be implemented to support
9309467b48Spatrick /// cases where this method returns success.
9409467b48Spatrick ///
analyzeBranch(MachineBasicBlock & MBB,MachineBasicBlock * & TBB,MachineBasicBlock * & FBB,SmallVectorImpl<MachineOperand> & Cond,bool AllowModify) const9509467b48Spatrick bool NVPTXInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
9609467b48Spatrick MachineBasicBlock *&TBB,
9709467b48Spatrick MachineBasicBlock *&FBB,
9809467b48Spatrick SmallVectorImpl<MachineOperand> &Cond,
9909467b48Spatrick bool AllowModify) const {
10009467b48Spatrick // If the block has no terminators, it just falls into the block after it.
10109467b48Spatrick MachineBasicBlock::iterator I = MBB.end();
10209467b48Spatrick if (I == MBB.begin() || !isUnpredicatedTerminator(*--I))
10309467b48Spatrick return false;
10409467b48Spatrick
10509467b48Spatrick // Get the last instruction in the block.
10609467b48Spatrick MachineInstr &LastInst = *I;
10709467b48Spatrick
10809467b48Spatrick // If there is only one terminator instruction, process it.
10909467b48Spatrick if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {
11009467b48Spatrick if (LastInst.getOpcode() == NVPTX::GOTO) {
11109467b48Spatrick TBB = LastInst.getOperand(0).getMBB();
11209467b48Spatrick return false;
11309467b48Spatrick } else if (LastInst.getOpcode() == NVPTX::CBranch) {
11409467b48Spatrick // Block ends with fall-through condbranch.
11509467b48Spatrick TBB = LastInst.getOperand(1).getMBB();
11609467b48Spatrick Cond.push_back(LastInst.getOperand(0));
11709467b48Spatrick return false;
11809467b48Spatrick }
11909467b48Spatrick // Otherwise, don't know what this is.
12009467b48Spatrick return true;
12109467b48Spatrick }
12209467b48Spatrick
12309467b48Spatrick // Get the instruction before it if it's a terminator.
12409467b48Spatrick MachineInstr &SecondLastInst = *I;
12509467b48Spatrick
12609467b48Spatrick // If there are three terminators, we don't know what sort of block this is.
12709467b48Spatrick if (I != MBB.begin() && isUnpredicatedTerminator(*--I))
12809467b48Spatrick return true;
12909467b48Spatrick
13009467b48Spatrick // If the block ends with NVPTX::GOTO and NVPTX:CBranch, handle it.
13109467b48Spatrick if (SecondLastInst.getOpcode() == NVPTX::CBranch &&
13209467b48Spatrick LastInst.getOpcode() == NVPTX::GOTO) {
13309467b48Spatrick TBB = SecondLastInst.getOperand(1).getMBB();
13409467b48Spatrick Cond.push_back(SecondLastInst.getOperand(0));
13509467b48Spatrick FBB = LastInst.getOperand(0).getMBB();
13609467b48Spatrick return false;
13709467b48Spatrick }
13809467b48Spatrick
13909467b48Spatrick // If the block ends with two NVPTX:GOTOs, handle it. The second one is not
14009467b48Spatrick // executed, so remove it.
14109467b48Spatrick if (SecondLastInst.getOpcode() == NVPTX::GOTO &&
14209467b48Spatrick LastInst.getOpcode() == NVPTX::GOTO) {
14309467b48Spatrick TBB = SecondLastInst.getOperand(0).getMBB();
14409467b48Spatrick I = LastInst;
14509467b48Spatrick if (AllowModify)
14609467b48Spatrick I->eraseFromParent();
14709467b48Spatrick return false;
14809467b48Spatrick }
14909467b48Spatrick
15009467b48Spatrick // Otherwise, can't handle this.
15109467b48Spatrick return true;
15209467b48Spatrick }
15309467b48Spatrick
removeBranch(MachineBasicBlock & MBB,int * BytesRemoved) const15409467b48Spatrick unsigned NVPTXInstrInfo::removeBranch(MachineBasicBlock &MBB,
15509467b48Spatrick int *BytesRemoved) const {
15609467b48Spatrick assert(!BytesRemoved && "code size not handled");
15709467b48Spatrick MachineBasicBlock::iterator I = MBB.end();
15809467b48Spatrick if (I == MBB.begin())
15909467b48Spatrick return 0;
16009467b48Spatrick --I;
16109467b48Spatrick if (I->getOpcode() != NVPTX::GOTO && I->getOpcode() != NVPTX::CBranch)
16209467b48Spatrick return 0;
16309467b48Spatrick
16409467b48Spatrick // Remove the branch.
16509467b48Spatrick I->eraseFromParent();
16609467b48Spatrick
16709467b48Spatrick I = MBB.end();
16809467b48Spatrick
16909467b48Spatrick if (I == MBB.begin())
17009467b48Spatrick return 1;
17109467b48Spatrick --I;
17209467b48Spatrick if (I->getOpcode() != NVPTX::CBranch)
17309467b48Spatrick return 1;
17409467b48Spatrick
17509467b48Spatrick // Remove the branch.
17609467b48Spatrick I->eraseFromParent();
17709467b48Spatrick return 2;
17809467b48Spatrick }
17909467b48Spatrick
insertBranch(MachineBasicBlock & MBB,MachineBasicBlock * TBB,MachineBasicBlock * FBB,ArrayRef<MachineOperand> Cond,const DebugLoc & DL,int * BytesAdded) const18009467b48Spatrick unsigned NVPTXInstrInfo::insertBranch(MachineBasicBlock &MBB,
18109467b48Spatrick MachineBasicBlock *TBB,
18209467b48Spatrick MachineBasicBlock *FBB,
18309467b48Spatrick ArrayRef<MachineOperand> Cond,
18409467b48Spatrick const DebugLoc &DL,
18509467b48Spatrick int *BytesAdded) const {
18609467b48Spatrick assert(!BytesAdded && "code size not handled");
18709467b48Spatrick
18809467b48Spatrick // Shouldn't be a fall through.
18909467b48Spatrick assert(TBB && "insertBranch must not be told to insert a fallthrough");
19009467b48Spatrick assert((Cond.size() == 1 || Cond.size() == 0) &&
19109467b48Spatrick "NVPTX branch conditions have two components!");
19209467b48Spatrick
19309467b48Spatrick // One-way branch.
19409467b48Spatrick if (!FBB) {
19509467b48Spatrick if (Cond.empty()) // Unconditional branch
19609467b48Spatrick BuildMI(&MBB, DL, get(NVPTX::GOTO)).addMBB(TBB);
19709467b48Spatrick else // Conditional branch
198*d415bd75Srobert BuildMI(&MBB, DL, get(NVPTX::CBranch)).add(Cond[0]).addMBB(TBB);
19909467b48Spatrick return 1;
20009467b48Spatrick }
20109467b48Spatrick
20209467b48Spatrick // Two-way Conditional Branch.
203*d415bd75Srobert BuildMI(&MBB, DL, get(NVPTX::CBranch)).add(Cond[0]).addMBB(TBB);
20409467b48Spatrick BuildMI(&MBB, DL, get(NVPTX::GOTO)).addMBB(FBB);
20509467b48Spatrick return 2;
20609467b48Spatrick }
207