Path: blob/main/contrib/llvm-project/llvm/lib/Target/VE/VEInstrInfo.cpp
35294 views
//===-- VEInstrInfo.cpp - VE Instruction Information ----------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file contains the VE implementation of the TargetInstrInfo class.9//10//===----------------------------------------------------------------------===//1112#include "VEInstrInfo.h"13#include "VE.h"14#include "VEMachineFunctionInfo.h"15#include "VESubtarget.h"16#include "llvm/ADT/STLExtras.h"17#include "llvm/ADT/SmallVector.h"18#include "llvm/CodeGen/MachineFrameInfo.h"19#include "llvm/CodeGen/MachineInstrBuilder.h"20#include "llvm/CodeGen/MachineMemOperand.h"21#include "llvm/CodeGen/MachineRegisterInfo.h"22#include "llvm/MC/TargetRegistry.h"23#include "llvm/Support/CommandLine.h"24#include "llvm/Support/Debug.h"25#include "llvm/Support/ErrorHandling.h"2627#define DEBUG_TYPE "ve-instr-info"2829using namespace llvm;3031#define GET_INSTRINFO_CTOR_DTOR32#include "VEGenInstrInfo.inc"3334// Pin the vtable to this file.35void VEInstrInfo::anchor() {}3637VEInstrInfo::VEInstrInfo(VESubtarget &ST)38: VEGenInstrInfo(VE::ADJCALLSTACKDOWN, VE::ADJCALLSTACKUP), RI() {}3940static bool IsIntegerCC(unsigned CC) { return (CC < VECC::CC_AF); }4142static VECC::CondCode GetOppositeBranchCondition(VECC::CondCode CC) {43switch (CC) {44case VECC::CC_IG:45return VECC::CC_ILE;46case VECC::CC_IL:47return VECC::CC_IGE;48case VECC::CC_INE:49return VECC::CC_IEQ;50case VECC::CC_IEQ:51return VECC::CC_INE;52case VECC::CC_IGE:53return VECC::CC_IL;54case VECC::CC_ILE:55return VECC::CC_IG;56case VECC::CC_AF:57return VECC::CC_AT;58case VECC::CC_G:59return VECC::CC_LENAN;60case VECC::CC_L:61return VECC::CC_GENAN;62case VECC::CC_NE:63return VECC::CC_EQNAN;64case VECC::CC_EQ:65return VECC::CC_NENAN;66case VECC::CC_GE:67return VECC::CC_LNAN;68case VECC::CC_LE:69return VECC::CC_GNAN;70case VECC::CC_NUM:71return VECC::CC_NAN;72case VECC::CC_NAN:73return VECC::CC_NUM;74case VECC::CC_GNAN:75return VECC::CC_LE;76case VECC::CC_LNAN:77return VECC::CC_GE;78case VECC::CC_NENAN:79return VECC::CC_EQ;80case VECC::CC_EQNAN:81return VECC::CC_NE;82case VECC::CC_GENAN:83return VECC::CC_L;84case VECC::CC_LENAN:85return VECC::CC_G;86case VECC::CC_AT:87return VECC::CC_AF;88case VECC::UNKNOWN:89return VECC::UNKNOWN;90}91llvm_unreachable("Invalid cond code");92}9394// Treat a branch relative long always instruction as unconditional branch.95// For example, br.l.t and br.l.96static bool isUncondBranchOpcode(int Opc) {97using namespace llvm::VE;9899#define BRKIND(NAME) (Opc == NAME##a || Opc == NAME##a_nt || Opc == NAME##a_t)100// VE has other branch relative always instructions for word/double/float,101// but we use only long branches in our lower. So, check it here.102assert(!BRKIND(BRCFW) && !BRKIND(BRCFD) && !BRKIND(BRCFS) &&103"Branch relative word/double/float always instructions should not be "104"used!");105return BRKIND(BRCFL);106#undef BRKIND107}108109// Treat branch relative conditional as conditional branch instructions.110// For example, brgt.l.t and brle.s.nt.111static bool isCondBranchOpcode(int Opc) {112using namespace llvm::VE;113114#define BRKIND(NAME) \115(Opc == NAME##rr || Opc == NAME##rr_nt || Opc == NAME##rr_t || \116Opc == NAME##ir || Opc == NAME##ir_nt || Opc == NAME##ir_t)117return BRKIND(BRCFL) || BRKIND(BRCFW) || BRKIND(BRCFD) || BRKIND(BRCFS);118#undef BRKIND119}120121// Treat branch long always instructions as indirect branch.122// For example, b.l.t and b.l.123static bool isIndirectBranchOpcode(int Opc) {124using namespace llvm::VE;125126#define BRKIND(NAME) \127(Opc == NAME##ari || Opc == NAME##ari_nt || Opc == NAME##ari_t)128// VE has other branch always instructions for word/double/float, but129// we use only long branches in our lower. So, check it here.130assert(!BRKIND(BCFW) && !BRKIND(BCFD) && !BRKIND(BCFS) &&131"Branch word/double/float always instructions should not be used!");132return BRKIND(BCFL);133#undef BRKIND134}135136static void parseCondBranch(MachineInstr *LastInst, MachineBasicBlock *&Target,137SmallVectorImpl<MachineOperand> &Cond) {138Cond.push_back(MachineOperand::CreateImm(LastInst->getOperand(0).getImm()));139Cond.push_back(LastInst->getOperand(1));140Cond.push_back(LastInst->getOperand(2));141Target = LastInst->getOperand(3).getMBB();142}143144bool VEInstrInfo::analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,145MachineBasicBlock *&FBB,146SmallVectorImpl<MachineOperand> &Cond,147bool AllowModify) const {148MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();149if (I == MBB.end())150return false;151152if (!isUnpredicatedTerminator(*I))153return false;154155// Get the last instruction in the block.156MachineInstr *LastInst = &*I;157unsigned LastOpc = LastInst->getOpcode();158159// If there is only one terminator instruction, process it.160if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {161if (isUncondBranchOpcode(LastOpc)) {162TBB = LastInst->getOperand(0).getMBB();163return false;164}165if (isCondBranchOpcode(LastOpc)) {166// Block ends with fall-through condbranch.167parseCondBranch(LastInst, TBB, Cond);168return false;169}170return true; // Can't handle indirect branch.171}172173// Get the instruction before it if it is a terminator.174MachineInstr *SecondLastInst = &*I;175unsigned SecondLastOpc = SecondLastInst->getOpcode();176177// If AllowModify is true and the block ends with two or more unconditional178// branches, delete all but the first unconditional branch.179if (AllowModify && isUncondBranchOpcode(LastOpc)) {180while (isUncondBranchOpcode(SecondLastOpc)) {181LastInst->eraseFromParent();182LastInst = SecondLastInst;183LastOpc = LastInst->getOpcode();184if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {185// Return now the only terminator is an unconditional branch.186TBB = LastInst->getOperand(0).getMBB();187return false;188}189SecondLastInst = &*I;190SecondLastOpc = SecondLastInst->getOpcode();191}192}193194// If there are three terminators, we don't know what sort of block this is.195if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(*--I))196return true;197198// If the block ends with a B and a Bcc, handle it.199if (isCondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {200parseCondBranch(SecondLastInst, TBB, Cond);201FBB = LastInst->getOperand(0).getMBB();202return false;203}204205// If the block ends with two unconditional branches, handle it. The second206// one is not executed.207if (isUncondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {208TBB = SecondLastInst->getOperand(0).getMBB();209return false;210}211212// ...likewise if it ends with an indirect branch followed by an unconditional213// branch.214if (isIndirectBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {215I = LastInst;216if (AllowModify)217I->eraseFromParent();218return true;219}220221// Otherwise, can't handle this.222return true;223}224225unsigned VEInstrInfo::insertBranch(MachineBasicBlock &MBB,226MachineBasicBlock *TBB,227MachineBasicBlock *FBB,228ArrayRef<MachineOperand> Cond,229const DebugLoc &DL, int *BytesAdded) const {230assert(TBB && "insertBranch must not be told to insert a fallthrough");231assert((Cond.size() == 3 || Cond.size() == 0) &&232"VE branch conditions should have three component!");233assert(!BytesAdded && "code size not handled");234if (Cond.empty()) {235// Uncondition branch236assert(!FBB && "Unconditional branch with multiple successors!");237BuildMI(&MBB, DL, get(VE::BRCFLa_t))238.addMBB(TBB);239return 1;240}241242// Conditional branch243// (BRCFir CC sy sz addr)244assert(Cond[0].isImm() && Cond[2].isReg() && "not implemented");245246unsigned opc[2];247const TargetRegisterInfo *TRI = &getRegisterInfo();248MachineFunction *MF = MBB.getParent();249const MachineRegisterInfo &MRI = MF->getRegInfo();250Register Reg = Cond[2].getReg();251if (IsIntegerCC(Cond[0].getImm())) {252if (TRI->getRegSizeInBits(Reg, MRI) == 32) {253opc[0] = VE::BRCFWir;254opc[1] = VE::BRCFWrr;255} else {256opc[0] = VE::BRCFLir;257opc[1] = VE::BRCFLrr;258}259} else {260if (TRI->getRegSizeInBits(Reg, MRI) == 32) {261opc[0] = VE::BRCFSir;262opc[1] = VE::BRCFSrr;263} else {264opc[0] = VE::BRCFDir;265opc[1] = VE::BRCFDrr;266}267}268if (Cond[1].isImm()) {269BuildMI(&MBB, DL, get(opc[0]))270.add(Cond[0]) // condition code271.add(Cond[1]) // lhs272.add(Cond[2]) // rhs273.addMBB(TBB);274} else {275BuildMI(&MBB, DL, get(opc[1]))276.add(Cond[0])277.add(Cond[1])278.add(Cond[2])279.addMBB(TBB);280}281282if (!FBB)283return 1;284285BuildMI(&MBB, DL, get(VE::BRCFLa_t))286.addMBB(FBB);287return 2;288}289290unsigned VEInstrInfo::removeBranch(MachineBasicBlock &MBB,291int *BytesRemoved) const {292assert(!BytesRemoved && "code size not handled");293294MachineBasicBlock::iterator I = MBB.end();295unsigned Count = 0;296while (I != MBB.begin()) {297--I;298299if (I->isDebugValue())300continue;301302if (!isUncondBranchOpcode(I->getOpcode()) &&303!isCondBranchOpcode(I->getOpcode()))304break; // Not a branch305306I->eraseFromParent();307I = MBB.end();308++Count;309}310return Count;311}312313bool VEInstrInfo::reverseBranchCondition(314SmallVectorImpl<MachineOperand> &Cond) const {315VECC::CondCode CC = static_cast<VECC::CondCode>(Cond[0].getImm());316Cond[0].setImm(GetOppositeBranchCondition(CC));317return false;318}319320static bool IsAliasOfSX(Register Reg) {321return VE::I32RegClass.contains(Reg) || VE::I64RegClass.contains(Reg) ||322VE::F32RegClass.contains(Reg);323}324325static void copyPhysSubRegs(MachineBasicBlock &MBB,326MachineBasicBlock::iterator I, const DebugLoc &DL,327MCRegister DestReg, MCRegister SrcReg, bool KillSrc,328const MCInstrDesc &MCID, unsigned int NumSubRegs,329const unsigned *SubRegIdx,330const TargetRegisterInfo *TRI) {331MachineInstr *MovMI = nullptr;332333for (unsigned Idx = 0; Idx != NumSubRegs; ++Idx) {334Register SubDest = TRI->getSubReg(DestReg, SubRegIdx[Idx]);335Register SubSrc = TRI->getSubReg(SrcReg, SubRegIdx[Idx]);336assert(SubDest && SubSrc && "Bad sub-register");337338if (MCID.getOpcode() == VE::ORri) {339// generate "ORri, dest, src, 0" instruction.340MachineInstrBuilder MIB =341BuildMI(MBB, I, DL, MCID, SubDest).addReg(SubSrc).addImm(0);342MovMI = MIB.getInstr();343} else if (MCID.getOpcode() == VE::ANDMmm) {344// generate "ANDM, dest, vm0, src" instruction.345MachineInstrBuilder MIB =346BuildMI(MBB, I, DL, MCID, SubDest).addReg(VE::VM0).addReg(SubSrc);347MovMI = MIB.getInstr();348} else {349llvm_unreachable("Unexpected reg-to-reg copy instruction");350}351}352// Add implicit super-register defs and kills to the last MovMI.353MovMI->addRegisterDefined(DestReg, TRI);354if (KillSrc)355MovMI->addRegisterKilled(SrcReg, TRI, true);356}357358void VEInstrInfo::copyPhysReg(MachineBasicBlock &MBB,359MachineBasicBlock::iterator I, const DebugLoc &DL,360MCRegister DestReg, MCRegister SrcReg,361bool KillSrc) const {362363if (IsAliasOfSX(SrcReg) && IsAliasOfSX(DestReg)) {364BuildMI(MBB, I, DL, get(VE::ORri), DestReg)365.addReg(SrcReg, getKillRegState(KillSrc))366.addImm(0);367} else if (VE::V64RegClass.contains(DestReg, SrcReg)) {368// Generate following instructions369// %sw16 = LEA32zii 256370// VORmvl %dest, (0)1, %src, %sw16371// TODO: reuse a register if vl is already assigned to a register372// FIXME: it would be better to scavenge a register here instead of373// reserving SX16 all of the time.374const TargetRegisterInfo *TRI = &getRegisterInfo();375Register TmpReg = VE::SX16;376Register SubTmp = TRI->getSubReg(TmpReg, VE::sub_i32);377BuildMI(MBB, I, DL, get(VE::LEAzii), TmpReg)378.addImm(0)379.addImm(0)380.addImm(256);381MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(VE::VORmvl), DestReg)382.addImm(M1(0)) // Represent (0)1.383.addReg(SrcReg, getKillRegState(KillSrc))384.addReg(SubTmp, getKillRegState(true));385MIB.getInstr()->addRegisterKilled(TmpReg, TRI, true);386} else if (VE::VMRegClass.contains(DestReg, SrcReg)) {387BuildMI(MBB, I, DL, get(VE::ANDMmm), DestReg)388.addReg(VE::VM0)389.addReg(SrcReg, getKillRegState(KillSrc));390} else if (VE::VM512RegClass.contains(DestReg, SrcReg)) {391// Use two instructions.392const unsigned SubRegIdx[] = {VE::sub_vm_even, VE::sub_vm_odd};393unsigned int NumSubRegs = 2;394copyPhysSubRegs(MBB, I, DL, DestReg, SrcReg, KillSrc, get(VE::ANDMmm),395NumSubRegs, SubRegIdx, &getRegisterInfo());396} else if (VE::F128RegClass.contains(DestReg, SrcReg)) {397// Use two instructions.398const unsigned SubRegIdx[] = {VE::sub_even, VE::sub_odd};399unsigned int NumSubRegs = 2;400copyPhysSubRegs(MBB, I, DL, DestReg, SrcReg, KillSrc, get(VE::ORri),401NumSubRegs, SubRegIdx, &getRegisterInfo());402} else {403const TargetRegisterInfo *TRI = &getRegisterInfo();404dbgs() << "Impossible reg-to-reg copy from " << printReg(SrcReg, TRI)405<< " to " << printReg(DestReg, TRI) << "\n";406llvm_unreachable("Impossible reg-to-reg copy");407}408}409410/// isLoadFromStackSlot - If the specified machine instruction is a direct411/// load from a stack slot, return the virtual or physical register number of412/// the destination along with the FrameIndex of the loaded stack slot. If413/// not, return 0. This predicate must return 0 if the instruction has414/// any side effects other than loading from the stack slot.415Register VEInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,416int &FrameIndex) const {417if (MI.getOpcode() == VE::LDrii || // I64418MI.getOpcode() == VE::LDLSXrii || // I32419MI.getOpcode() == VE::LDUrii || // F32420MI.getOpcode() == VE::LDQrii || // F128 (pseudo)421MI.getOpcode() == VE::LDVMrii || // VM (pseudo)422MI.getOpcode() == VE::LDVM512rii // VM512 (pseudo)423) {424if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&425MI.getOperand(2).getImm() == 0 && MI.getOperand(3).isImm() &&426MI.getOperand(3).getImm() == 0) {427FrameIndex = MI.getOperand(1).getIndex();428return MI.getOperand(0).getReg();429}430}431return 0;432}433434/// isStoreToStackSlot - If the specified machine instruction is a direct435/// store to a stack slot, return the virtual or physical register number of436/// the source reg along with the FrameIndex of the loaded stack slot. If437/// not, return 0. This predicate must return 0 if the instruction has438/// any side effects other than storing to the stack slot.439Register VEInstrInfo::isStoreToStackSlot(const MachineInstr &MI,440int &FrameIndex) const {441if (MI.getOpcode() == VE::STrii || // I64442MI.getOpcode() == VE::STLrii || // I32443MI.getOpcode() == VE::STUrii || // F32444MI.getOpcode() == VE::STQrii || // F128 (pseudo)445MI.getOpcode() == VE::STVMrii || // VM (pseudo)446MI.getOpcode() == VE::STVM512rii // VM512 (pseudo)447) {448if (MI.getOperand(0).isFI() && MI.getOperand(1).isImm() &&449MI.getOperand(1).getImm() == 0 && MI.getOperand(2).isImm() &&450MI.getOperand(2).getImm() == 0) {451FrameIndex = MI.getOperand(0).getIndex();452return MI.getOperand(3).getReg();453}454}455return 0;456}457458void VEInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,459MachineBasicBlock::iterator I,460Register SrcReg, bool isKill, int FI,461const TargetRegisterClass *RC,462const TargetRegisterInfo *TRI,463Register VReg) const {464DebugLoc DL;465if (I != MBB.end())466DL = I->getDebugLoc();467468MachineFunction *MF = MBB.getParent();469const MachineFrameInfo &MFI = MF->getFrameInfo();470MachineMemOperand *MMO = MF->getMachineMemOperand(471MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOStore,472MFI.getObjectSize(FI), MFI.getObjectAlign(FI));473474// On the order of operands here: think "[FrameIdx + 0] = SrcReg".475if (RC == &VE::I64RegClass) {476BuildMI(MBB, I, DL, get(VE::STrii))477.addFrameIndex(FI)478.addImm(0)479.addImm(0)480.addReg(SrcReg, getKillRegState(isKill))481.addMemOperand(MMO);482} else if (RC == &VE::I32RegClass) {483BuildMI(MBB, I, DL, get(VE::STLrii))484.addFrameIndex(FI)485.addImm(0)486.addImm(0)487.addReg(SrcReg, getKillRegState(isKill))488.addMemOperand(MMO);489} else if (RC == &VE::F32RegClass) {490BuildMI(MBB, I, DL, get(VE::STUrii))491.addFrameIndex(FI)492.addImm(0)493.addImm(0)494.addReg(SrcReg, getKillRegState(isKill))495.addMemOperand(MMO);496} else if (VE::F128RegClass.hasSubClassEq(RC)) {497BuildMI(MBB, I, DL, get(VE::STQrii))498.addFrameIndex(FI)499.addImm(0)500.addImm(0)501.addReg(SrcReg, getKillRegState(isKill))502.addMemOperand(MMO);503} else if (RC == &VE::VMRegClass) {504BuildMI(MBB, I, DL, get(VE::STVMrii))505.addFrameIndex(FI)506.addImm(0)507.addImm(0)508.addReg(SrcReg, getKillRegState(isKill))509.addMemOperand(MMO);510} else if (VE::VM512RegClass.hasSubClassEq(RC)) {511BuildMI(MBB, I, DL, get(VE::STVM512rii))512.addFrameIndex(FI)513.addImm(0)514.addImm(0)515.addReg(SrcReg, getKillRegState(isKill))516.addMemOperand(MMO);517} else518report_fatal_error("Can't store this register to stack slot");519}520521void VEInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,522MachineBasicBlock::iterator I,523Register DestReg, int FI,524const TargetRegisterClass *RC,525const TargetRegisterInfo *TRI,526Register VReg) const {527DebugLoc DL;528if (I != MBB.end())529DL = I->getDebugLoc();530531MachineFunction *MF = MBB.getParent();532const MachineFrameInfo &MFI = MF->getFrameInfo();533MachineMemOperand *MMO = MF->getMachineMemOperand(534MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOLoad,535MFI.getObjectSize(FI), MFI.getObjectAlign(FI));536537if (RC == &VE::I64RegClass) {538BuildMI(MBB, I, DL, get(VE::LDrii), DestReg)539.addFrameIndex(FI)540.addImm(0)541.addImm(0)542.addMemOperand(MMO);543} else if (RC == &VE::I32RegClass) {544BuildMI(MBB, I, DL, get(VE::LDLSXrii), DestReg)545.addFrameIndex(FI)546.addImm(0)547.addImm(0)548.addMemOperand(MMO);549} else if (RC == &VE::F32RegClass) {550BuildMI(MBB, I, DL, get(VE::LDUrii), DestReg)551.addFrameIndex(FI)552.addImm(0)553.addImm(0)554.addMemOperand(MMO);555} else if (VE::F128RegClass.hasSubClassEq(RC)) {556BuildMI(MBB, I, DL, get(VE::LDQrii), DestReg)557.addFrameIndex(FI)558.addImm(0)559.addImm(0)560.addMemOperand(MMO);561} else if (RC == &VE::VMRegClass) {562BuildMI(MBB, I, DL, get(VE::LDVMrii), DestReg)563.addFrameIndex(FI)564.addImm(0)565.addImm(0)566.addMemOperand(MMO);567} else if (VE::VM512RegClass.hasSubClassEq(RC)) {568BuildMI(MBB, I, DL, get(VE::LDVM512rii), DestReg)569.addFrameIndex(FI)570.addImm(0)571.addImm(0)572.addMemOperand(MMO);573} else574report_fatal_error("Can't load this register from stack slot");575}576577bool VEInstrInfo::foldImmediate(MachineInstr &UseMI, MachineInstr &DefMI,578Register Reg, MachineRegisterInfo *MRI) const {579LLVM_DEBUG(dbgs() << "foldImmediate\n");580581LLVM_DEBUG(dbgs() << "checking DefMI\n");582int64_t ImmVal;583switch (DefMI.getOpcode()) {584default:585return false;586case VE::ORim:587// General move small immediate instruction on VE.588LLVM_DEBUG(dbgs() << "checking ORim\n");589LLVM_DEBUG(DefMI.dump());590// FIXME: We may need to support FPImm too.591assert(DefMI.getOperand(1).isImm());592assert(DefMI.getOperand(2).isImm());593ImmVal =594DefMI.getOperand(1).getImm() + mimm2Val(DefMI.getOperand(2).getImm());595LLVM_DEBUG(dbgs() << "ImmVal is " << ImmVal << "\n");596break;597case VE::LEAzii:598// General move immediate instruction on VE.599LLVM_DEBUG(dbgs() << "checking LEAzii\n");600LLVM_DEBUG(DefMI.dump());601// FIXME: We may need to support FPImm too.602assert(DefMI.getOperand(2).isImm());603if (!DefMI.getOperand(3).isImm())604// LEAzii may refer label605return false;606ImmVal = DefMI.getOperand(2).getImm() + DefMI.getOperand(3).getImm();607LLVM_DEBUG(dbgs() << "ImmVal is " << ImmVal << "\n");608break;609}610611// Try to fold like below:612// %1:i64 = ORim 0, 0(1)613// %2:i64 = CMPSLrr %0, %1614// To615// %2:i64 = CMPSLrm %0, 0(1)616//617// Another example:618// %1:i64 = ORim 6, 0(1)619// %2:i64 = CMPSLrr %1, %0620// To621// %2:i64 = CMPSLir 6, %0622//623// Support commutable instructions like below:624// %1:i64 = ORim 6, 0(1)625// %2:i64 = ADDSLrr %1, %0626// To627// %2:i64 = ADDSLri %0, 6628//629// FIXME: Need to support i32. Current implementtation requires630// EXTRACT_SUBREG, so input has following COPY and it avoids folding:631// %1:i64 = ORim 6, 0(1)632// %2:i32 = COPY %1.sub_i32633// %3:i32 = ADDSWSXrr %0, %2634// FIXME: Need to support shift, cmov, and more instructions.635// FIXME: Need to support lvl too, but LVLGen runs after peephole-opt.636637LLVM_DEBUG(dbgs() << "checking UseMI\n");638LLVM_DEBUG(UseMI.dump());639unsigned NewUseOpcSImm7;640unsigned NewUseOpcMImm;641enum InstType {642rr2ri_rm, // rr -> ri or rm, commutable643rr2ir_rm, // rr -> ir or rm644} InstType;645646using namespace llvm::VE;647#define INSTRKIND(NAME) \648case NAME##rr: \649NewUseOpcSImm7 = NAME##ri; \650NewUseOpcMImm = NAME##rm; \651InstType = rr2ri_rm; \652break653#define NCINSTRKIND(NAME) \654case NAME##rr: \655NewUseOpcSImm7 = NAME##ir; \656NewUseOpcMImm = NAME##rm; \657InstType = rr2ir_rm; \658break659660switch (UseMI.getOpcode()) {661default:662return false;663664INSTRKIND(ADDUL);665INSTRKIND(ADDSWSX);666INSTRKIND(ADDSWZX);667INSTRKIND(ADDSL);668NCINSTRKIND(SUBUL);669NCINSTRKIND(SUBSWSX);670NCINSTRKIND(SUBSWZX);671NCINSTRKIND(SUBSL);672INSTRKIND(MULUL);673INSTRKIND(MULSWSX);674INSTRKIND(MULSWZX);675INSTRKIND(MULSL);676NCINSTRKIND(DIVUL);677NCINSTRKIND(DIVSWSX);678NCINSTRKIND(DIVSWZX);679NCINSTRKIND(DIVSL);680NCINSTRKIND(CMPUL);681NCINSTRKIND(CMPSWSX);682NCINSTRKIND(CMPSWZX);683NCINSTRKIND(CMPSL);684INSTRKIND(MAXSWSX);685INSTRKIND(MAXSWZX);686INSTRKIND(MAXSL);687INSTRKIND(MINSWSX);688INSTRKIND(MINSWZX);689INSTRKIND(MINSL);690INSTRKIND(AND);691INSTRKIND(OR);692INSTRKIND(XOR);693INSTRKIND(EQV);694NCINSTRKIND(NND);695NCINSTRKIND(MRG);696}697698#undef INSTRKIND699700unsigned NewUseOpc;701unsigned UseIdx;702bool Commute = false;703LLVM_DEBUG(dbgs() << "checking UseMI operands\n");704switch (InstType) {705case rr2ri_rm:706UseIdx = 2;707if (UseMI.getOperand(1).getReg() == Reg) {708Commute = true;709} else {710assert(UseMI.getOperand(2).getReg() == Reg);711}712if (isInt<7>(ImmVal)) {713// This ImmVal matches to SImm7 slot, so change UseOpc to an instruction714// holds a simm7 slot.715NewUseOpc = NewUseOpcSImm7;716} else if (isMImmVal(ImmVal)) {717// Similarly, change UseOpc to an instruction holds a mimm slot.718NewUseOpc = NewUseOpcMImm;719ImmVal = val2MImm(ImmVal);720} else721return false;722break;723case rr2ir_rm:724if (UseMI.getOperand(1).getReg() == Reg) {725// Check immediate value whether it matchs to the UseMI instruction.726if (!isInt<7>(ImmVal))727return false;728NewUseOpc = NewUseOpcSImm7;729UseIdx = 1;730} else {731assert(UseMI.getOperand(2).getReg() == Reg);732// Check immediate value whether it matchs to the UseMI instruction.733if (!isMImmVal(ImmVal))734return false;735NewUseOpc = NewUseOpcMImm;736ImmVal = val2MImm(ImmVal);737UseIdx = 2;738}739break;740}741742LLVM_DEBUG(dbgs() << "modifying UseMI\n");743bool DeleteDef = MRI->hasOneNonDBGUse(Reg);744UseMI.setDesc(get(NewUseOpc));745if (Commute) {746UseMI.getOperand(1).setReg(UseMI.getOperand(UseIdx).getReg());747}748UseMI.getOperand(UseIdx).ChangeToImmediate(ImmVal);749if (DeleteDef)750DefMI.eraseFromParent();751752return true;753}754755Register VEInstrInfo::getGlobalBaseReg(MachineFunction *MF) const {756VEMachineFunctionInfo *VEFI = MF->getInfo<VEMachineFunctionInfo>();757Register GlobalBaseReg = VEFI->getGlobalBaseReg();758if (GlobalBaseReg != 0)759return GlobalBaseReg;760761// We use %s15 (%got) as a global base register762GlobalBaseReg = VE::SX15;763764// Insert a pseudo instruction to set the GlobalBaseReg into the first765// MBB of the function766MachineBasicBlock &FirstMBB = MF->front();767MachineBasicBlock::iterator MBBI = FirstMBB.begin();768DebugLoc dl;769BuildMI(FirstMBB, MBBI, dl, get(VE::GETGOT), GlobalBaseReg);770VEFI->setGlobalBaseReg(GlobalBaseReg);771return GlobalBaseReg;772}773774static Register getVM512Upper(Register reg) {775return (reg - VE::VMP0) * 2 + VE::VM0;776}777778static Register getVM512Lower(Register reg) { return getVM512Upper(reg) + 1; }779780// Expand pseudo logical vector instructions for VM512 registers.781static void expandPseudoLogM(MachineInstr &MI, const MCInstrDesc &MCID) {782MachineBasicBlock *MBB = MI.getParent();783DebugLoc DL = MI.getDebugLoc();784785Register VMXu = getVM512Upper(MI.getOperand(0).getReg());786Register VMXl = getVM512Lower(MI.getOperand(0).getReg());787Register VMYu = getVM512Upper(MI.getOperand(1).getReg());788Register VMYl = getVM512Lower(MI.getOperand(1).getReg());789790switch (MI.getOpcode()) {791default: {792Register VMZu = getVM512Upper(MI.getOperand(2).getReg());793Register VMZl = getVM512Lower(MI.getOperand(2).getReg());794BuildMI(*MBB, MI, DL, MCID).addDef(VMXu).addUse(VMYu).addUse(VMZu);795BuildMI(*MBB, MI, DL, MCID).addDef(VMXl).addUse(VMYl).addUse(VMZl);796break;797}798case VE::NEGMy:799BuildMI(*MBB, MI, DL, MCID).addDef(VMXu).addUse(VMYu);800BuildMI(*MBB, MI, DL, MCID).addDef(VMXl).addUse(VMYl);801break;802}803MI.eraseFromParent();804}805806static void addOperandsForVFMK(MachineInstrBuilder &MIB, MachineInstr &MI,807bool Upper) {808// VM512809MIB.addReg(Upper ? getVM512Upper(MI.getOperand(0).getReg())810: getVM512Lower(MI.getOperand(0).getReg()));811812switch (MI.getNumExplicitOperands()) {813default:814report_fatal_error("unexpected number of operands for pvfmk");815case 2: // _Ml: VM512, VL816// VL817MIB.addReg(MI.getOperand(1).getReg());818break;819case 4: // _Mvl: VM512, CC, VR, VL820// CC821MIB.addImm(MI.getOperand(1).getImm());822// VR823MIB.addReg(MI.getOperand(2).getReg());824// VL825MIB.addReg(MI.getOperand(3).getReg());826break;827case 5: // _MvMl: VM512, CC, VR, VM512, VL828// CC829MIB.addImm(MI.getOperand(1).getImm());830// VR831MIB.addReg(MI.getOperand(2).getReg());832// VM512833MIB.addReg(Upper ? getVM512Upper(MI.getOperand(3).getReg())834: getVM512Lower(MI.getOperand(3).getReg()));835// VL836MIB.addReg(MI.getOperand(4).getReg());837break;838}839}840841static void expandPseudoVFMK(const TargetInstrInfo &TI, MachineInstr &MI) {842// replace to pvfmk.w.up and pvfmk.w.lo843// replace to pvfmk.s.up and pvfmk.s.lo844845static const std::pair<unsigned, std::pair<unsigned, unsigned>> VFMKMap[] = {846{VE::VFMKyal, {VE::VFMKLal, VE::VFMKLal}},847{VE::VFMKynal, {VE::VFMKLnal, VE::VFMKLnal}},848{VE::VFMKWyvl, {VE::PVFMKWUPvl, VE::PVFMKWLOvl}},849{VE::VFMKWyvyl, {VE::PVFMKWUPvml, VE::PVFMKWLOvml}},850{VE::VFMKSyvl, {VE::PVFMKSUPvl, VE::PVFMKSLOvl}},851{VE::VFMKSyvyl, {VE::PVFMKSUPvml, VE::PVFMKSLOvml}},852};853854unsigned Opcode = MI.getOpcode();855856const auto *Found =857llvm::find_if(VFMKMap, [&](auto P) { return P.first == Opcode; });858if (Found == std::end(VFMKMap))859report_fatal_error("unexpected opcode for pseudo vfmk");860861unsigned OpcodeUpper = (*Found).second.first;862unsigned OpcodeLower = (*Found).second.second;863864MachineBasicBlock *MBB = MI.getParent();865DebugLoc DL = MI.getDebugLoc();866867MachineInstrBuilder Bu = BuildMI(*MBB, MI, DL, TI.get(OpcodeUpper));868addOperandsForVFMK(Bu, MI, /* Upper */ true);869MachineInstrBuilder Bl = BuildMI(*MBB, MI, DL, TI.get(OpcodeLower));870addOperandsForVFMK(Bl, MI, /* Upper */ false);871872MI.eraseFromParent();873}874875bool VEInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {876switch (MI.getOpcode()) {877case VE::EXTEND_STACK: {878return expandExtendStackPseudo(MI);879}880case VE::EXTEND_STACK_GUARD: {881MI.eraseFromParent(); // The pseudo instruction is gone now.882return true;883}884case VE::GETSTACKTOP: {885return expandGetStackTopPseudo(MI);886}887888case VE::ANDMyy:889expandPseudoLogM(MI, get(VE::ANDMmm));890return true;891case VE::ORMyy:892expandPseudoLogM(MI, get(VE::ORMmm));893return true;894case VE::XORMyy:895expandPseudoLogM(MI, get(VE::XORMmm));896return true;897case VE::EQVMyy:898expandPseudoLogM(MI, get(VE::EQVMmm));899return true;900case VE::NNDMyy:901expandPseudoLogM(MI, get(VE::NNDMmm));902return true;903case VE::NEGMy:904expandPseudoLogM(MI, get(VE::NEGMm));905return true;906907case VE::LVMyir:908case VE::LVMyim:909case VE::LVMyir_y:910case VE::LVMyim_y: {911Register VMXu = getVM512Upper(MI.getOperand(0).getReg());912Register VMXl = getVM512Lower(MI.getOperand(0).getReg());913int64_t Imm = MI.getOperand(1).getImm();914bool IsSrcReg =915MI.getOpcode() == VE::LVMyir || MI.getOpcode() == VE::LVMyir_y;916Register Src = IsSrcReg ? MI.getOperand(2).getReg() : VE::NoRegister;917int64_t MImm = IsSrcReg ? 0 : MI.getOperand(2).getImm();918bool KillSrc = IsSrcReg ? MI.getOperand(2).isKill() : false;919Register VMX = VMXl;920if (Imm >= 4) {921VMX = VMXu;922Imm -= 4;923}924MachineBasicBlock *MBB = MI.getParent();925DebugLoc DL = MI.getDebugLoc();926switch (MI.getOpcode()) {927case VE::LVMyir:928BuildMI(*MBB, MI, DL, get(VE::LVMir))929.addDef(VMX)930.addImm(Imm)931.addReg(Src, getKillRegState(KillSrc));932break;933case VE::LVMyim:934BuildMI(*MBB, MI, DL, get(VE::LVMim))935.addDef(VMX)936.addImm(Imm)937.addImm(MImm);938break;939case VE::LVMyir_y:940assert(MI.getOperand(0).getReg() == MI.getOperand(3).getReg() &&941"LVMyir_y has different register in 3rd operand");942BuildMI(*MBB, MI, DL, get(VE::LVMir_m))943.addDef(VMX)944.addImm(Imm)945.addReg(Src, getKillRegState(KillSrc))946.addReg(VMX);947break;948case VE::LVMyim_y:949assert(MI.getOperand(0).getReg() == MI.getOperand(3).getReg() &&950"LVMyim_y has different register in 3rd operand");951BuildMI(*MBB, MI, DL, get(VE::LVMim_m))952.addDef(VMX)953.addImm(Imm)954.addImm(MImm)955.addReg(VMX);956break;957}958MI.eraseFromParent();959return true;960}961case VE::SVMyi: {962Register Dest = MI.getOperand(0).getReg();963Register VMZu = getVM512Upper(MI.getOperand(1).getReg());964Register VMZl = getVM512Lower(MI.getOperand(1).getReg());965bool KillSrc = MI.getOperand(1).isKill();966int64_t Imm = MI.getOperand(2).getImm();967Register VMZ = VMZl;968if (Imm >= 4) {969VMZ = VMZu;970Imm -= 4;971}972MachineBasicBlock *MBB = MI.getParent();973DebugLoc DL = MI.getDebugLoc();974MachineInstrBuilder MIB =975BuildMI(*MBB, MI, DL, get(VE::SVMmi), Dest).addReg(VMZ).addImm(Imm);976MachineInstr *Inst = MIB.getInstr();977if (KillSrc) {978const TargetRegisterInfo *TRI = &getRegisterInfo();979Inst->addRegisterKilled(MI.getOperand(1).getReg(), TRI, true);980}981MI.eraseFromParent();982return true;983}984case VE::VFMKyal:985case VE::VFMKynal:986case VE::VFMKWyvl:987case VE::VFMKWyvyl:988case VE::VFMKSyvl:989case VE::VFMKSyvyl:990expandPseudoVFMK(*this, MI);991return true;992}993return false;994}995996bool VEInstrInfo::expandExtendStackPseudo(MachineInstr &MI) const {997MachineBasicBlock &MBB = *MI.getParent();998MachineFunction &MF = *MBB.getParent();999const VESubtarget &STI = MF.getSubtarget<VESubtarget>();1000const VEInstrInfo &TII = *STI.getInstrInfo();1001DebugLoc dl = MBB.findDebugLoc(MI);10021003// Create following instructions and multiple basic blocks.1004//1005// thisBB:1006// brge.l.t %sp, %sl, sinkBB1007// syscallBB:1008// ld %s61, 0x18(, %tp) // load param area1009// or %s62, 0, %s0 // spill the value of %s01010// lea %s63, 0x13b // syscall # of grow1011// shm.l %s63, 0x0(%s61) // store syscall # at addr:01012// shm.l %sl, 0x8(%s61) // store old limit at addr:81013// shm.l %sp, 0x10(%s61) // store new limit at addr:161014// monc // call monitor1015// or %s0, 0, %s62 // restore the value of %s01016// sinkBB:10171018// Create new MBB1019MachineBasicBlock *BB = &MBB;1020const BasicBlock *LLVM_BB = BB->getBasicBlock();1021MachineBasicBlock *syscallMBB = MF.CreateMachineBasicBlock(LLVM_BB);1022MachineBasicBlock *sinkMBB = MF.CreateMachineBasicBlock(LLVM_BB);1023MachineFunction::iterator It = ++(BB->getIterator());1024MF.insert(It, syscallMBB);1025MF.insert(It, sinkMBB);10261027// Transfer the remainder of BB and its successor edges to sinkMBB.1028sinkMBB->splice(sinkMBB->begin(), BB,1029std::next(std::next(MachineBasicBlock::iterator(MI))),1030BB->end());1031sinkMBB->transferSuccessorsAndUpdatePHIs(BB);10321033// Next, add the true and fallthrough blocks as its successors.1034BB->addSuccessor(syscallMBB);1035BB->addSuccessor(sinkMBB);1036BuildMI(BB, dl, TII.get(VE::BRCFLrr_t))1037.addImm(VECC::CC_IGE)1038.addReg(VE::SX11) // %sp1039.addReg(VE::SX8) // %sl1040.addMBB(sinkMBB);10411042BB = syscallMBB;10431044// Update machine-CFG edges1045BB->addSuccessor(sinkMBB);10461047BuildMI(BB, dl, TII.get(VE::LDrii), VE::SX61)1048.addReg(VE::SX14)1049.addImm(0)1050.addImm(0x18);1051BuildMI(BB, dl, TII.get(VE::ORri), VE::SX62)1052.addReg(VE::SX0)1053.addImm(0);1054BuildMI(BB, dl, TII.get(VE::LEAzii), VE::SX63)1055.addImm(0)1056.addImm(0)1057.addImm(0x13b);1058BuildMI(BB, dl, TII.get(VE::SHMLri))1059.addReg(VE::SX61)1060.addImm(0)1061.addReg(VE::SX63);1062BuildMI(BB, dl, TII.get(VE::SHMLri))1063.addReg(VE::SX61)1064.addImm(8)1065.addReg(VE::SX8);1066BuildMI(BB, dl, TII.get(VE::SHMLri))1067.addReg(VE::SX61)1068.addImm(16)1069.addReg(VE::SX11);1070BuildMI(BB, dl, TII.get(VE::MONC));10711072BuildMI(BB, dl, TII.get(VE::ORri), VE::SX0)1073.addReg(VE::SX62)1074.addImm(0);10751076MI.eraseFromParent(); // The pseudo instruction is gone now.1077return true;1078}10791080bool VEInstrInfo::expandGetStackTopPseudo(MachineInstr &MI) const {1081MachineBasicBlock *MBB = MI.getParent();1082MachineFunction &MF = *MBB->getParent();1083const VESubtarget &STI = MF.getSubtarget<VESubtarget>();1084const VEInstrInfo &TII = *STI.getInstrInfo();1085DebugLoc DL = MBB->findDebugLoc(MI);10861087// Create following instruction1088//1089// dst = %sp + target specific frame + the size of parameter area10901091const MachineFrameInfo &MFI = MF.getFrameInfo();1092const VEFrameLowering &TFL = *STI.getFrameLowering();10931094// The VE ABI requires a reserved area at the top of stack as described1095// in VEFrameLowering.cpp. So, we adjust it here.1096unsigned NumBytes = STI.getAdjustedFrameSize(0);10971098// Also adds the size of parameter area.1099if (MFI.adjustsStack() && TFL.hasReservedCallFrame(MF))1100NumBytes += MFI.getMaxCallFrameSize();11011102BuildMI(*MBB, MI, DL, TII.get(VE::LEArii))1103.addDef(MI.getOperand(0).getReg())1104.addReg(VE::SX11)1105.addImm(0)1106.addImm(NumBytes);11071108MI.eraseFromParent(); // The pseudo instruction is gone now.1109return true;1110}111111121113