brintos

brintos / llvm-project-archived public Read only

0
0
Text · 36.7 KiB · b9ac5d6 Raw
1111 lines · cpp
1//===-- VEInstrInfo.cpp - VE Instruction Information ----------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains the VE implementation of the TargetInstrInfo class.10//11//===----------------------------------------------------------------------===//12 13#include "VEInstrInfo.h"14#include "VE.h"15#include "VEMachineFunctionInfo.h"16#include "VESubtarget.h"17#include "llvm/ADT/STLExtras.h"18#include "llvm/ADT/SmallVector.h"19#include "llvm/CodeGen/MachineFrameInfo.h"20#include "llvm/CodeGen/MachineInstrBuilder.h"21#include "llvm/CodeGen/MachineMemOperand.h"22#include "llvm/CodeGen/MachineRegisterInfo.h"23#include "llvm/MC/TargetRegistry.h"24#include "llvm/Support/Debug.h"25#include "llvm/Support/ErrorHandling.h"26 27#define DEBUG_TYPE "ve-instr-info"28 29using namespace llvm;30 31#define GET_INSTRINFO_CTOR_DTOR32#include "VEGenInstrInfo.inc"33 34// Pin the vtable to this file.35void VEInstrInfo::anchor() {}36 37VEInstrInfo::VEInstrInfo(const VESubtarget &ST)38    : VEGenInstrInfo(ST, RI, VE::ADJCALLSTACKDOWN, VE::ADJCALLSTACKUP), RI() {}39 40static bool IsIntegerCC(unsigned CC) { return (CC < VECC::CC_AF); }41 42static VECC::CondCode GetOppositeBranchCondition(VECC::CondCode CC) {43  switch (CC) {44  case VECC::CC_IG:45    return VECC::CC_ILE;46  case VECC::CC_IL:47    return VECC::CC_IGE;48  case VECC::CC_INE:49    return VECC::CC_IEQ;50  case VECC::CC_IEQ:51    return VECC::CC_INE;52  case VECC::CC_IGE:53    return VECC::CC_IL;54  case VECC::CC_ILE:55    return VECC::CC_IG;56  case VECC::CC_AF:57    return VECC::CC_AT;58  case VECC::CC_G:59    return VECC::CC_LENAN;60  case VECC::CC_L:61    return VECC::CC_GENAN;62  case VECC::CC_NE:63    return VECC::CC_EQNAN;64  case VECC::CC_EQ:65    return VECC::CC_NENAN;66  case VECC::CC_GE:67    return VECC::CC_LNAN;68  case VECC::CC_LE:69    return VECC::CC_GNAN;70  case VECC::CC_NUM:71    return VECC::CC_NAN;72  case VECC::CC_NAN:73    return VECC::CC_NUM;74  case VECC::CC_GNAN:75    return VECC::CC_LE;76  case VECC::CC_LNAN:77    return VECC::CC_GE;78  case VECC::CC_NENAN:79    return VECC::CC_EQ;80  case VECC::CC_EQNAN:81    return VECC::CC_NE;82  case VECC::CC_GENAN:83    return VECC::CC_L;84  case VECC::CC_LENAN:85    return VECC::CC_G;86  case VECC::CC_AT:87    return VECC::CC_AF;88  case VECC::UNKNOWN:89    return VECC::UNKNOWN;90  }91  llvm_unreachable("Invalid cond code");92}93 94// Treat a branch relative long always instruction as unconditional branch.95// For example, br.l.t and br.l.96static bool isUncondBranchOpcode(int Opc) {97  using namespace llvm::VE;98 99#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.102  assert(!BRKIND(BRCFW) && !BRKIND(BRCFD) && !BRKIND(BRCFS) &&103         "Branch relative word/double/float always instructions should not be "104         "used!");105  return BRKIND(BRCFL);106#undef BRKIND107}108 109// Treat branch relative conditional as conditional branch instructions.110// For example, brgt.l.t and brle.s.nt.111static bool isCondBranchOpcode(int Opc) {112  using namespace llvm::VE;113 114#define BRKIND(NAME)                                                           \115  (Opc == NAME##rr || Opc == NAME##rr_nt || Opc == NAME##rr_t ||               \116   Opc == NAME##ir || Opc == NAME##ir_nt || Opc == NAME##ir_t)117  return BRKIND(BRCFL) || BRKIND(BRCFW) || BRKIND(BRCFD) || BRKIND(BRCFS);118#undef BRKIND119}120 121// Treat branch long always instructions as indirect branch.122// For example, b.l.t and b.l.123static bool isIndirectBranchOpcode(int Opc) {124  using namespace llvm::VE;125 126#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.130  assert(!BRKIND(BCFW) && !BRKIND(BCFD) && !BRKIND(BCFS) &&131         "Branch word/double/float always instructions should not be used!");132  return BRKIND(BCFL);133#undef BRKIND134}135 136static void parseCondBranch(MachineInstr *LastInst, MachineBasicBlock *&Target,137                            SmallVectorImpl<MachineOperand> &Cond) {138  Cond.push_back(MachineOperand::CreateImm(LastInst->getOperand(0).getImm()));139  Cond.push_back(LastInst->getOperand(1));140  Cond.push_back(LastInst->getOperand(2));141  Target = LastInst->getOperand(3).getMBB();142}143 144bool VEInstrInfo::analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,145                                MachineBasicBlock *&FBB,146                                SmallVectorImpl<MachineOperand> &Cond,147                                bool AllowModify) const {148  MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();149  if (I == MBB.end())150    return false;151 152  if (!isUnpredicatedTerminator(*I))153    return false;154 155  // Get the last instruction in the block.156  MachineInstr *LastInst = &*I;157  unsigned LastOpc = LastInst->getOpcode();158 159  // If there is only one terminator instruction, process it.160  if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {161    if (isUncondBranchOpcode(LastOpc)) {162      TBB = LastInst->getOperand(0).getMBB();163      return false;164    }165    if (isCondBranchOpcode(LastOpc)) {166      // Block ends with fall-through condbranch.167      parseCondBranch(LastInst, TBB, Cond);168      return false;169    }170    return true; // Can't handle indirect branch.171  }172 173  // Get the instruction before it if it is a terminator.174  MachineInstr *SecondLastInst = &*I;175  unsigned SecondLastOpc = SecondLastInst->getOpcode();176 177  // If AllowModify is true and the block ends with two or more unconditional178  // branches, delete all but the first unconditional branch.179  if (AllowModify && isUncondBranchOpcode(LastOpc)) {180    while (isUncondBranchOpcode(SecondLastOpc)) {181      LastInst->eraseFromParent();182      LastInst = SecondLastInst;183      LastOpc = LastInst->getOpcode();184      if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {185        // Return now the only terminator is an unconditional branch.186        TBB = LastInst->getOperand(0).getMBB();187        return false;188      }189      SecondLastInst = &*I;190      SecondLastOpc = SecondLastInst->getOpcode();191    }192  }193 194  // If there are three terminators, we don't know what sort of block this is.195  if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(*--I))196    return true;197 198  // If the block ends with a B and a Bcc, handle it.199  if (isCondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {200    parseCondBranch(SecondLastInst, TBB, Cond);201    FBB = LastInst->getOperand(0).getMBB();202    return false;203  }204 205  // If the block ends with two unconditional branches, handle it.  The second206  // one is not executed.207  if (isUncondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {208    TBB = SecondLastInst->getOperand(0).getMBB();209    return false;210  }211 212  // ...likewise if it ends with an indirect branch followed by an unconditional213  // branch.214  if (isIndirectBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {215    I = LastInst;216    if (AllowModify)217      I->eraseFromParent();218    return true;219  }220 221  // Otherwise, can't handle this.222  return true;223}224 225unsigned VEInstrInfo::insertBranch(MachineBasicBlock &MBB,226                                   MachineBasicBlock *TBB,227                                   MachineBasicBlock *FBB,228                                   ArrayRef<MachineOperand> Cond,229                                   const DebugLoc &DL, int *BytesAdded) const {230  assert(TBB && "insertBranch must not be told to insert a fallthrough");231  assert((Cond.size() == 3 || Cond.size() == 0) &&232         "VE branch conditions should have three component!");233  assert(!BytesAdded && "code size not handled");234  if (Cond.empty()) {235    // Uncondition branch236    assert(!FBB && "Unconditional branch with multiple successors!");237    BuildMI(&MBB, DL, get(VE::BRCFLa_t))238        .addMBB(TBB);239    return 1;240  }241 242  // Conditional branch243  //   (BRCFir CC sy sz addr)244  assert(Cond[0].isImm() && Cond[2].isReg() && "not implemented");245 246  unsigned opc[2];247  const TargetRegisterInfo *TRI = &getRegisterInfo();248  MachineFunction *MF = MBB.getParent();249  const MachineRegisterInfo &MRI = MF->getRegInfo();250  Register Reg = Cond[2].getReg();251  if (IsIntegerCC(Cond[0].getImm())) {252    if (TRI->getRegSizeInBits(Reg, MRI) == 32) {253      opc[0] = VE::BRCFWir;254      opc[1] = VE::BRCFWrr;255    } else {256      opc[0] = VE::BRCFLir;257      opc[1] = VE::BRCFLrr;258    }259  } else {260    if (TRI->getRegSizeInBits(Reg, MRI) == 32) {261      opc[0] = VE::BRCFSir;262      opc[1] = VE::BRCFSrr;263    } else {264      opc[0] = VE::BRCFDir;265      opc[1] = VE::BRCFDrr;266    }267  }268  if (Cond[1].isImm()) {269      BuildMI(&MBB, DL, get(opc[0]))270          .add(Cond[0]) // condition code271          .add(Cond[1]) // lhs272          .add(Cond[2]) // rhs273          .addMBB(TBB);274  } else {275      BuildMI(&MBB, DL, get(opc[1]))276          .add(Cond[0])277          .add(Cond[1])278          .add(Cond[2])279          .addMBB(TBB);280  }281 282  if (!FBB)283    return 1;284 285  BuildMI(&MBB, DL, get(VE::BRCFLa_t))286      .addMBB(FBB);287  return 2;288}289 290unsigned VEInstrInfo::removeBranch(MachineBasicBlock &MBB,291                                   int *BytesRemoved) const {292  assert(!BytesRemoved && "code size not handled");293 294  MachineBasicBlock::iterator I = MBB.end();295  unsigned Count = 0;296  while (I != MBB.begin()) {297    --I;298 299    if (I->isDebugValue())300      continue;301 302    if (!isUncondBranchOpcode(I->getOpcode()) &&303        !isCondBranchOpcode(I->getOpcode()))304      break; // Not a branch305 306    I->eraseFromParent();307    I = MBB.end();308    ++Count;309  }310  return Count;311}312 313bool VEInstrInfo::reverseBranchCondition(314    SmallVectorImpl<MachineOperand> &Cond) const {315  VECC::CondCode CC = static_cast<VECC::CondCode>(Cond[0].getImm());316  Cond[0].setImm(GetOppositeBranchCondition(CC));317  return false;318}319 320static bool IsAliasOfSX(Register Reg) {321  return VE::I32RegClass.contains(Reg) || VE::I64RegClass.contains(Reg) ||322         VE::F32RegClass.contains(Reg);323}324 325static void copyPhysSubRegs(MachineBasicBlock &MBB,326                            MachineBasicBlock::iterator I, const DebugLoc &DL,327                            MCRegister DestReg, MCRegister SrcReg, bool KillSrc,328                            const MCInstrDesc &MCID, unsigned int NumSubRegs,329                            const unsigned *SubRegIdx,330                            const TargetRegisterInfo *TRI) {331  MachineInstr *MovMI = nullptr;332 333  for (unsigned Idx = 0; Idx != NumSubRegs; ++Idx) {334    Register SubDest = TRI->getSubReg(DestReg, SubRegIdx[Idx]);335    Register SubSrc = TRI->getSubReg(SrcReg, SubRegIdx[Idx]);336    assert(SubDest && SubSrc && "Bad sub-register");337 338    if (MCID.getOpcode() == VE::ORri) {339      // generate "ORri, dest, src, 0" instruction.340      MachineInstrBuilder MIB =341          BuildMI(MBB, I, DL, MCID, SubDest).addReg(SubSrc).addImm(0);342      MovMI = MIB.getInstr();343    } else if (MCID.getOpcode() == VE::ANDMmm) {344      // generate "ANDM, dest, vm0, src" instruction.345      MachineInstrBuilder MIB =346          BuildMI(MBB, I, DL, MCID, SubDest).addReg(VE::VM0).addReg(SubSrc);347      MovMI = MIB.getInstr();348    } else {349      llvm_unreachable("Unexpected reg-to-reg copy instruction");350    }351  }352  // Add implicit super-register defs and kills to the last MovMI.353  MovMI->addRegisterDefined(DestReg, TRI);354  if (KillSrc)355    MovMI->addRegisterKilled(SrcReg, TRI, true);356}357 358void VEInstrInfo::copyPhysReg(MachineBasicBlock &MBB,359                              MachineBasicBlock::iterator I, const DebugLoc &DL,360                              Register DestReg, Register SrcReg, bool KillSrc,361                              bool RenamableDest, bool RenamableSrc) const {362 363  if (IsAliasOfSX(SrcReg) && IsAliasOfSX(DestReg)) {364    BuildMI(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.374    const TargetRegisterInfo *TRI = &getRegisterInfo();375    Register TmpReg = VE::SX16;376    Register SubTmp = TRI->getSubReg(TmpReg, VE::sub_i32);377    BuildMI(MBB, I, DL, get(VE::LEAzii), TmpReg)378        .addImm(0)379        .addImm(0)380        .addImm(256);381    MachineInstrBuilder 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));385    MIB.getInstr()->addRegisterKilled(TmpReg, TRI, true);386  } else if (VE::VMRegClass.contains(DestReg, SrcReg)) {387    BuildMI(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.392    const unsigned SubRegIdx[] = {VE::sub_vm_even, VE::sub_vm_odd};393    unsigned int NumSubRegs = 2;394    copyPhysSubRegs(MBB, I, DL, DestReg, SrcReg, KillSrc, get(VE::ANDMmm),395                    NumSubRegs, SubRegIdx, &getRegisterInfo());396  } else if (VE::F128RegClass.contains(DestReg, SrcReg)) {397    // Use two instructions.398    const unsigned SubRegIdx[] = {VE::sub_even, VE::sub_odd};399    unsigned int NumSubRegs = 2;400    copyPhysSubRegs(MBB, I, DL, DestReg, SrcReg, KillSrc, get(VE::ORri),401                    NumSubRegs, SubRegIdx, &getRegisterInfo());402  } else {403    const TargetRegisterInfo *TRI = &getRegisterInfo();404    dbgs() << "Impossible reg-to-reg copy from " << printReg(SrcReg, TRI)405           << " to " << printReg(DestReg, TRI) << "\n";406    llvm_unreachable("Impossible reg-to-reg copy");407  }408}409 410/// 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,416                                          int &FrameIndex) const {417  if (MI.getOpcode() == VE::LDrii ||    // I64418      MI.getOpcode() == VE::LDLSXrii || // I32419      MI.getOpcode() == VE::LDUrii ||   // F32420      MI.getOpcode() == VE::LDQrii ||   // F128 (pseudo)421      MI.getOpcode() == VE::LDVMrii ||  // VM (pseudo)422      MI.getOpcode() == VE::LDVM512rii  // VM512 (pseudo)423  ) {424    if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&425        MI.getOperand(2).getImm() == 0 && MI.getOperand(3).isImm() &&426        MI.getOperand(3).getImm() == 0) {427      FrameIndex = MI.getOperand(1).getIndex();428      return MI.getOperand(0).getReg();429    }430  }431  return 0;432}433 434/// 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,440                                         int &FrameIndex) const {441  if (MI.getOpcode() == VE::STrii ||   // I64442      MI.getOpcode() == VE::STLrii ||  // I32443      MI.getOpcode() == VE::STUrii ||  // F32444      MI.getOpcode() == VE::STQrii ||  // F128 (pseudo)445      MI.getOpcode() == VE::STVMrii || // VM (pseudo)446      MI.getOpcode() == VE::STVM512rii // VM512 (pseudo)447  ) {448    if (MI.getOperand(0).isFI() && MI.getOperand(1).isImm() &&449        MI.getOperand(1).getImm() == 0 && MI.getOperand(2).isImm() &&450        MI.getOperand(2).getImm() == 0) {451      FrameIndex = MI.getOperand(0).getIndex();452      return MI.getOperand(3).getReg();453    }454  }455  return 0;456}457 458void VEInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,459                                      MachineBasicBlock::iterator I,460                                      Register SrcReg, bool isKill, int FI,461                                      const TargetRegisterClass *RC,462                                      Register VReg,463                                      MachineInstr::MIFlag Flags) const {464  DebugLoc DL;465  if (I != MBB.end())466    DL = I->getDebugLoc();467 468  MachineFunction *MF = MBB.getParent();469  const MachineFrameInfo &MFI = MF->getFrameInfo();470  MachineMemOperand *MMO = MF->getMachineMemOperand(471      MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOStore,472      MFI.getObjectSize(FI), MFI.getObjectAlign(FI));473 474  // On the order of operands here: think "[FrameIdx + 0] = SrcReg".475  if (RC == &VE::I64RegClass) {476    BuildMI(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) {483    BuildMI(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) {490    BuildMI(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)) {497    BuildMI(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) {504    BuildMI(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)) {511    BuildMI(MBB, I, DL, get(VE::STVM512rii))512        .addFrameIndex(FI)513        .addImm(0)514        .addImm(0)515        .addReg(SrcReg, getKillRegState(isKill))516        .addMemOperand(MMO);517  } else518    report_fatal_error("Can't store this register to stack slot");519}520 521void VEInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,522                                       MachineBasicBlock::iterator I,523                                       Register DestReg, int FI,524                                       const TargetRegisterClass *RC,525                                       Register VReg,526                                       MachineInstr::MIFlag Flags) const {527  DebugLoc DL;528  if (I != MBB.end())529    DL = I->getDebugLoc();530 531  MachineFunction *MF = MBB.getParent();532  const MachineFrameInfo &MFI = MF->getFrameInfo();533  MachineMemOperand *MMO = MF->getMachineMemOperand(534      MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOLoad,535      MFI.getObjectSize(FI), MFI.getObjectAlign(FI));536 537  if (RC == &VE::I64RegClass) {538    BuildMI(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) {544    BuildMI(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) {550    BuildMI(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)) {556    BuildMI(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) {562    BuildMI(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)) {568    BuildMI(MBB, I, DL, get(VE::LDVM512rii), DestReg)569        .addFrameIndex(FI)570        .addImm(0)571        .addImm(0)572        .addMemOperand(MMO);573  } else574    report_fatal_error("Can't load this register from stack slot");575}576 577bool VEInstrInfo::foldImmediate(MachineInstr &UseMI, MachineInstr &DefMI,578                                Register Reg, MachineRegisterInfo *MRI) const {579  LLVM_DEBUG(dbgs() << "foldImmediate\n");580 581  LLVM_DEBUG(dbgs() << "checking DefMI\n");582  int64_t ImmVal;583  switch (DefMI.getOpcode()) {584  default:585    return false;586  case VE::ORim:587    // General move small immediate instruction on VE.588    LLVM_DEBUG(dbgs() << "checking ORim\n");589    LLVM_DEBUG(DefMI.dump());590    // FIXME: We may need to support FPImm too.591    assert(DefMI.getOperand(1).isImm());592    assert(DefMI.getOperand(2).isImm());593    ImmVal =594        DefMI.getOperand(1).getImm() + mimm2Val(DefMI.getOperand(2).getImm());595    LLVM_DEBUG(dbgs() << "ImmVal is " << ImmVal << "\n");596    break;597  case VE::LEAzii:598    // General move immediate instruction on VE.599    LLVM_DEBUG(dbgs() << "checking LEAzii\n");600    LLVM_DEBUG(DefMI.dump());601    // FIXME: We may need to support FPImm too.602    assert(DefMI.getOperand(2).isImm());603    if (!DefMI.getOperand(3).isImm())604      // LEAzii may refer label605      return false;606    ImmVal = DefMI.getOperand(2).getImm() + DefMI.getOperand(3).getImm();607    LLVM_DEBUG(dbgs() << "ImmVal is " << ImmVal << "\n");608    break;609  }610 611  // 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.636 637  LLVM_DEBUG(dbgs() << "checking UseMI\n");638  LLVM_DEBUG(UseMI.dump());639  unsigned NewUseOpcSImm7;640  unsigned NewUseOpcMImm;641  enum InstType {642    rr2ri_rm, // rr -> ri or rm, commutable643    rr2ir_rm, // rr -> ir or rm644  } InstType;645 646  using namespace llvm::VE;647#define INSTRKIND(NAME)                                                        \648  case NAME##rr:                                                               \649    NewUseOpcSImm7 = NAME##ri;                                                 \650    NewUseOpcMImm = NAME##rm;                                                  \651    InstType = rr2ri_rm;                                                       \652    break653#define NCINSTRKIND(NAME)                                                      \654  case NAME##rr:                                                               \655    NewUseOpcSImm7 = NAME##ir;                                                 \656    NewUseOpcMImm = NAME##rm;                                                  \657    InstType = rr2ir_rm;                                                       \658    break659 660  switch (UseMI.getOpcode()) {661  default:662    return false;663 664    INSTRKIND(ADDUL);665    INSTRKIND(ADDSWSX);666    INSTRKIND(ADDSWZX);667    INSTRKIND(ADDSL);668    NCINSTRKIND(SUBUL);669    NCINSTRKIND(SUBSWSX);670    NCINSTRKIND(SUBSWZX);671    NCINSTRKIND(SUBSL);672    INSTRKIND(MULUL);673    INSTRKIND(MULSWSX);674    INSTRKIND(MULSWZX);675    INSTRKIND(MULSL);676    NCINSTRKIND(DIVUL);677    NCINSTRKIND(DIVSWSX);678    NCINSTRKIND(DIVSWZX);679    NCINSTRKIND(DIVSL);680    NCINSTRKIND(CMPUL);681    NCINSTRKIND(CMPSWSX);682    NCINSTRKIND(CMPSWZX);683    NCINSTRKIND(CMPSL);684    INSTRKIND(MAXSWSX);685    INSTRKIND(MAXSWZX);686    INSTRKIND(MAXSL);687    INSTRKIND(MINSWSX);688    INSTRKIND(MINSWZX);689    INSTRKIND(MINSL);690    INSTRKIND(AND);691    INSTRKIND(OR);692    INSTRKIND(XOR);693    INSTRKIND(EQV);694    NCINSTRKIND(NND);695    NCINSTRKIND(MRG);696  }697 698#undef INSTRKIND699 700  unsigned NewUseOpc;701  unsigned UseIdx;702  bool Commute = false;703  LLVM_DEBUG(dbgs() << "checking UseMI operands\n");704  switch (InstType) {705  case rr2ri_rm:706    UseIdx = 2;707    if (UseMI.getOperand(1).getReg() == Reg) {708      Commute = true;709    } else {710      assert(UseMI.getOperand(2).getReg() == Reg);711    }712    if (isInt<7>(ImmVal)) {713      // This ImmVal matches to SImm7 slot, so change UseOpc to an instruction714      // holds a simm7 slot.715      NewUseOpc = NewUseOpcSImm7;716    } else if (isMImmVal(ImmVal)) {717      // Similarly, change UseOpc to an instruction holds a mimm slot.718      NewUseOpc = NewUseOpcMImm;719      ImmVal = val2MImm(ImmVal);720    } else721      return false;722    break;723  case rr2ir_rm:724    if (UseMI.getOperand(1).getReg() == Reg) {725      // Check immediate value whether it matchs to the UseMI instruction.726      if (!isInt<7>(ImmVal))727        return false;728      NewUseOpc = NewUseOpcSImm7;729      UseIdx = 1;730    } else {731      assert(UseMI.getOperand(2).getReg() == Reg);732      // Check immediate value whether it matchs to the UseMI instruction.733      if (!isMImmVal(ImmVal))734        return false;735      NewUseOpc = NewUseOpcMImm;736      ImmVal = val2MImm(ImmVal);737      UseIdx = 2;738    }739    break;740  }741 742  LLVM_DEBUG(dbgs() << "modifying UseMI\n");743  bool DeleteDef = MRI->hasOneNonDBGUse(Reg);744  UseMI.setDesc(get(NewUseOpc));745  if (Commute) {746    UseMI.getOperand(1).setReg(UseMI.getOperand(UseIdx).getReg());747  }748  UseMI.getOperand(UseIdx).ChangeToImmediate(ImmVal);749  if (DeleteDef)750    DefMI.eraseFromParent();751 752  return true;753}754 755Register VEInstrInfo::getGlobalBaseReg(MachineFunction *MF) const {756  VEMachineFunctionInfo *VEFI = MF->getInfo<VEMachineFunctionInfo>();757  Register GlobalBaseReg = VEFI->getGlobalBaseReg();758  if (GlobalBaseReg != 0)759    return GlobalBaseReg;760 761  // We use %s15 (%got) as a global base register762  GlobalBaseReg = VE::SX15;763 764  // Insert a pseudo instruction to set the GlobalBaseReg into the first765  // MBB of the function766  MachineBasicBlock &FirstMBB = MF->front();767  MachineBasicBlock::iterator MBBI = FirstMBB.begin();768  DebugLoc dl;769  BuildMI(FirstMBB, MBBI, dl, get(VE::GETGOT), GlobalBaseReg);770  VEFI->setGlobalBaseReg(GlobalBaseReg);771  return GlobalBaseReg;772}773 774static Register getVM512Upper(Register reg) {775  return (reg - VE::VMP0) * 2 + VE::VM0;776}777 778static Register getVM512Lower(Register reg) { return getVM512Upper(reg) + 1; }779 780// Expand pseudo logical vector instructions for VM512 registers.781static void expandPseudoLogM(MachineInstr &MI, const MCInstrDesc &MCID) {782  MachineBasicBlock *MBB = MI.getParent();783  DebugLoc DL = MI.getDebugLoc();784 785  Register VMXu = getVM512Upper(MI.getOperand(0).getReg());786  Register VMXl = getVM512Lower(MI.getOperand(0).getReg());787  Register VMYu = getVM512Upper(MI.getOperand(1).getReg());788  Register VMYl = getVM512Lower(MI.getOperand(1).getReg());789 790  switch (MI.getOpcode()) {791  default: {792    Register VMZu = getVM512Upper(MI.getOperand(2).getReg());793    Register VMZl = getVM512Lower(MI.getOperand(2).getReg());794    BuildMI(*MBB, MI, DL, MCID).addDef(VMXu).addUse(VMYu).addUse(VMZu);795    BuildMI(*MBB, MI, DL, MCID).addDef(VMXl).addUse(VMYl).addUse(VMZl);796    break;797  }798  case VE::NEGMy:799    BuildMI(*MBB, MI, DL, MCID).addDef(VMXu).addUse(VMYu);800    BuildMI(*MBB, MI, DL, MCID).addDef(VMXl).addUse(VMYl);801    break;802  }803  MI.eraseFromParent();804}805 806static void addOperandsForVFMK(MachineInstrBuilder &MIB, MachineInstr &MI,807                               bool Upper) {808  // VM512809  MIB.addReg(Upper ? getVM512Upper(MI.getOperand(0).getReg())810                   : getVM512Lower(MI.getOperand(0).getReg()));811 812  switch (MI.getNumExplicitOperands()) {813  default:814    report_fatal_error("unexpected number of operands for pvfmk");815  case 2: // _Ml: VM512, VL816    // VL817    MIB.addReg(MI.getOperand(1).getReg());818    break;819  case 4: // _Mvl: VM512, CC, VR, VL820    // CC821    MIB.addImm(MI.getOperand(1).getImm());822    // VR823    MIB.addReg(MI.getOperand(2).getReg());824    // VL825    MIB.addReg(MI.getOperand(3).getReg());826    break;827  case 5: // _MvMl: VM512, CC, VR, VM512, VL828    // CC829    MIB.addImm(MI.getOperand(1).getImm());830    // VR831    MIB.addReg(MI.getOperand(2).getReg());832    // VM512833    MIB.addReg(Upper ? getVM512Upper(MI.getOperand(3).getReg())834                     : getVM512Lower(MI.getOperand(3).getReg()));835    // VL836    MIB.addReg(MI.getOperand(4).getReg());837    break;838  }839}840 841static 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.lo844 845  static 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  };853 854  unsigned Opcode = MI.getOpcode();855 856  const auto *Found =857      llvm::find_if(VFMKMap, [&](auto P) { return P.first == Opcode; });858  if (Found == std::end(VFMKMap))859    report_fatal_error("unexpected opcode for pseudo vfmk");860 861  unsigned OpcodeUpper = (*Found).second.first;862  unsigned OpcodeLower = (*Found).second.second;863 864  MachineBasicBlock *MBB = MI.getParent();865  DebugLoc DL = MI.getDebugLoc();866 867  MachineInstrBuilder Bu = BuildMI(*MBB, MI, DL, TI.get(OpcodeUpper));868  addOperandsForVFMK(Bu, MI, /* Upper */ true);869  MachineInstrBuilder Bl = BuildMI(*MBB, MI, DL, TI.get(OpcodeLower));870  addOperandsForVFMK(Bl, MI, /* Upper */ false);871 872  MI.eraseFromParent();873}874 875bool VEInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {876  switch (MI.getOpcode()) {877  case VE::EXTEND_STACK: {878    return expandExtendStackPseudo(MI);879  }880  case VE::EXTEND_STACK_GUARD: {881    MI.eraseFromParent(); // The pseudo instruction is gone now.882    return true;883  }884  case VE::GETSTACKTOP: {885    return expandGetStackTopPseudo(MI);886  }887 888  case VE::ANDMyy:889    expandPseudoLogM(MI, get(VE::ANDMmm));890    return true;891  case VE::ORMyy:892    expandPseudoLogM(MI, get(VE::ORMmm));893    return true;894  case VE::XORMyy:895    expandPseudoLogM(MI, get(VE::XORMmm));896    return true;897  case VE::EQVMyy:898    expandPseudoLogM(MI, get(VE::EQVMmm));899    return true;900  case VE::NNDMyy:901    expandPseudoLogM(MI, get(VE::NNDMmm));902    return true;903  case VE::NEGMy:904    expandPseudoLogM(MI, get(VE::NEGMm));905    return true;906 907  case VE::LVMyir:908  case VE::LVMyim:909  case VE::LVMyir_y:910  case VE::LVMyim_y: {911    Register VMXu = getVM512Upper(MI.getOperand(0).getReg());912    Register VMXl = getVM512Lower(MI.getOperand(0).getReg());913    int64_t Imm = MI.getOperand(1).getImm();914    bool IsSrcReg =915        MI.getOpcode() == VE::LVMyir || MI.getOpcode() == VE::LVMyir_y;916    Register Src = IsSrcReg ? MI.getOperand(2).getReg() : VE::NoRegister;917    int64_t MImm = IsSrcReg ? 0 : MI.getOperand(2).getImm();918    bool KillSrc = IsSrcReg ? MI.getOperand(2).isKill() : false;919    Register VMX = VMXl;920    if (Imm >= 4) {921      VMX = VMXu;922      Imm -= 4;923    }924    MachineBasicBlock *MBB = MI.getParent();925    DebugLoc DL = MI.getDebugLoc();926    switch (MI.getOpcode()) {927    case VE::LVMyir:928      BuildMI(*MBB, MI, DL, get(VE::LVMir))929          .addDef(VMX)930          .addImm(Imm)931          .addReg(Src, getKillRegState(KillSrc));932      break;933    case VE::LVMyim:934      BuildMI(*MBB, MI, DL, get(VE::LVMim))935          .addDef(VMX)936          .addImm(Imm)937          .addImm(MImm);938      break;939    case VE::LVMyir_y:940      assert(MI.getOperand(0).getReg() == MI.getOperand(3).getReg() &&941             "LVMyir_y has different register in 3rd operand");942      BuildMI(*MBB, MI, DL, get(VE::LVMir_m))943          .addDef(VMX)944          .addImm(Imm)945          .addReg(Src, getKillRegState(KillSrc))946          .addReg(VMX);947      break;948    case VE::LVMyim_y:949      assert(MI.getOperand(0).getReg() == MI.getOperand(3).getReg() &&950             "LVMyim_y has different register in 3rd operand");951      BuildMI(*MBB, MI, DL, get(VE::LVMim_m))952          .addDef(VMX)953          .addImm(Imm)954          .addImm(MImm)955          .addReg(VMX);956      break;957    }958    MI.eraseFromParent();959    return true;960  }961  case VE::SVMyi: {962    Register Dest = MI.getOperand(0).getReg();963    Register VMZu = getVM512Upper(MI.getOperand(1).getReg());964    Register VMZl = getVM512Lower(MI.getOperand(1).getReg());965    bool KillSrc = MI.getOperand(1).isKill();966    int64_t Imm = MI.getOperand(2).getImm();967    Register VMZ = VMZl;968    if (Imm >= 4) {969      VMZ = VMZu;970      Imm -= 4;971    }972    MachineBasicBlock *MBB = MI.getParent();973    DebugLoc DL = MI.getDebugLoc();974    MachineInstrBuilder MIB =975        BuildMI(*MBB, MI, DL, get(VE::SVMmi), Dest).addReg(VMZ).addImm(Imm);976    MachineInstr *Inst = MIB.getInstr();977    if (KillSrc) {978      const TargetRegisterInfo *TRI = &getRegisterInfo();979      Inst->addRegisterKilled(MI.getOperand(1).getReg(), TRI, true);980    }981    MI.eraseFromParent();982    return true;983  }984  case VE::VFMKyal:985  case VE::VFMKynal:986  case VE::VFMKWyvl:987  case VE::VFMKWyvyl:988  case VE::VFMKSyvl:989  case VE::VFMKSyvyl:990    expandPseudoVFMK(*this, MI);991    return true;992  }993  return false;994}995 996bool VEInstrInfo::expandExtendStackPseudo(MachineInstr &MI) const {997  MachineBasicBlock &MBB = *MI.getParent();998  MachineFunction &MF = *MBB.getParent();999  const VESubtarget &STI = MF.getSubtarget<VESubtarget>();1000  const VEInstrInfo &TII = *STI.getInstrInfo();1001  DebugLoc dl = MBB.findDebugLoc(MI);1002 1003  // 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:1017 1018  // Create new MBB1019  MachineBasicBlock *BB = &MBB;1020  const BasicBlock *LLVM_BB = BB->getBasicBlock();1021  MachineBasicBlock *syscallMBB = MF.CreateMachineBasicBlock(LLVM_BB);1022  MachineBasicBlock *sinkMBB = MF.CreateMachineBasicBlock(LLVM_BB);1023  MachineFunction::iterator It = ++(BB->getIterator());1024  MF.insert(It, syscallMBB);1025  MF.insert(It, sinkMBB);1026 1027  // Transfer the remainder of BB and its successor edges to sinkMBB.1028  sinkMBB->splice(sinkMBB->begin(), BB,1029                  std::next(std::next(MachineBasicBlock::iterator(MI))),1030                  BB->end());1031  sinkMBB->transferSuccessorsAndUpdatePHIs(BB);1032 1033  // Next, add the true and fallthrough blocks as its successors.1034  BB->addSuccessor(syscallMBB);1035  BB->addSuccessor(sinkMBB);1036  BuildMI(BB, dl, TII.get(VE::BRCFLrr_t))1037      .addImm(VECC::CC_IGE)1038      .addReg(VE::SX11) // %sp1039      .addReg(VE::SX8)  // %sl1040      .addMBB(sinkMBB);1041 1042  BB = syscallMBB;1043 1044  // Update machine-CFG edges1045  BB->addSuccessor(sinkMBB);1046 1047  BuildMI(BB, dl, TII.get(VE::LDrii), VE::SX61)1048      .addReg(VE::SX14)1049      .addImm(0)1050      .addImm(0x18);1051  BuildMI(BB, dl, TII.get(VE::ORri), VE::SX62)1052      .addReg(VE::SX0)1053      .addImm(0);1054  BuildMI(BB, dl, TII.get(VE::LEAzii), VE::SX63)1055      .addImm(0)1056      .addImm(0)1057      .addImm(0x13b);1058  BuildMI(BB, dl, TII.get(VE::SHMLri))1059      .addReg(VE::SX61)1060      .addImm(0)1061      .addReg(VE::SX63);1062  BuildMI(BB, dl, TII.get(VE::SHMLri))1063      .addReg(VE::SX61)1064      .addImm(8)1065      .addReg(VE::SX8);1066  BuildMI(BB, dl, TII.get(VE::SHMLri))1067      .addReg(VE::SX61)1068      .addImm(16)1069      .addReg(VE::SX11);1070  BuildMI(BB, dl, TII.get(VE::MONC));1071 1072  BuildMI(BB, dl, TII.get(VE::ORri), VE::SX0)1073      .addReg(VE::SX62)1074      .addImm(0);1075 1076  MI.eraseFromParent(); // The pseudo instruction is gone now.1077  return true;1078}1079 1080bool VEInstrInfo::expandGetStackTopPseudo(MachineInstr &MI) const {1081  MachineBasicBlock *MBB = MI.getParent();1082  MachineFunction &MF = *MBB->getParent();1083  const VESubtarget &STI = MF.getSubtarget<VESubtarget>();1084  const VEInstrInfo &TII = *STI.getInstrInfo();1085  DebugLoc DL = MBB->findDebugLoc(MI);1086 1087  // Create following instruction1088  //1089  //   dst = %sp + target specific frame + the size of parameter area1090 1091  const MachineFrameInfo &MFI = MF.getFrameInfo();1092  const VEFrameLowering &TFL = *STI.getFrameLowering();1093 1094  // The VE ABI requires a reserved area at the top of stack as described1095  // in VEFrameLowering.cpp.  So, we adjust it here.1096  unsigned NumBytes = STI.getAdjustedFrameSize(0);1097 1098  // Also adds the size of parameter area.1099  if (MFI.adjustsStack() && TFL.hasReservedCallFrame(MF))1100    NumBytes += MFI.getMaxCallFrameSize();1101 1102  BuildMI(*MBB, MI, DL, TII.get(VE::LEArii))1103      .addDef(MI.getOperand(0).getReg())1104      .addReg(VE::SX11)1105      .addImm(0)1106      .addImm(NumBytes);1107 1108  MI.eraseFromParent(); // The pseudo instruction is gone now.1109  return true;1110}1111