brintos

brintos / llvm-project-archived public Read only

0
0
Text · 26.6 KiB · ea98cdb Raw
852 lines · cpp
1//===- RISCVOptWInstrs.cpp - MI W instruction optimizations ---------------===//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 pass does some optimizations for *W instructions at the MI level.10//11// First it removes unneeded sext.w instructions. Either because the sign12// extended bits aren't consumed or because the input was already sign extended13// by an earlier instruction.14//15// Then:16// 1. Unless explicit disabled or the target prefers instructions with W suffix,17//    it removes the -w suffix from opw instructions whenever all users are18//    dependent only on the lower word of the result of the instruction.19//    The cases handled are:20//    * addw because c.add has a larger register encoding than c.addw.21//    * addiw because it helps reduce test differences between RV32 and RV6422//      w/o being a pessimization.23//    * mulw because c.mulw doesn't exist but c.mul does (w/ zcb)24//    * slliw because c.slliw doesn't exist and c.slli does25//26// 2. Or if explicit enabled or the target prefers instructions with W suffix,27//    it adds the W suffix to the instruction whenever all users are dependent28//    only on the lower word of the result of the instruction.29//    The cases handled are:30//    * add/addi/sub/mul.31//    * slli with imm < 32.32//    * ld/lwu.33//===---------------------------------------------------------------------===//34 35#include "RISCV.h"36#include "RISCVMachineFunctionInfo.h"37#include "RISCVSubtarget.h"38#include "llvm/ADT/SmallSet.h"39#include "llvm/ADT/Statistic.h"40#include "llvm/CodeGen/MachineFunctionPass.h"41#include "llvm/CodeGen/TargetInstrInfo.h"42 43using namespace llvm;44 45#define DEBUG_TYPE "riscv-opt-w-instrs"46#define RISCV_OPT_W_INSTRS_NAME "RISC-V Optimize W Instructions"47 48STATISTIC(NumRemovedSExtW, "Number of removed sign-extensions");49STATISTIC(NumTransformedToWInstrs,50          "Number of instructions transformed to W-ops");51STATISTIC(NumTransformedToNonWInstrs,52          "Number of instructions transformed to non-W-ops");53 54static cl::opt<bool> DisableSExtWRemoval("riscv-disable-sextw-removal",55                                         cl::desc("Disable removal of sext.w"),56                                         cl::init(false), cl::Hidden);57static cl::opt<bool> DisableStripWSuffix("riscv-disable-strip-w-suffix",58                                         cl::desc("Disable strip W suffix"),59                                         cl::init(false), cl::Hidden);60 61namespace {62 63class RISCVOptWInstrs : public MachineFunctionPass {64public:65  static char ID;66 67  RISCVOptWInstrs() : MachineFunctionPass(ID) {}68 69  bool runOnMachineFunction(MachineFunction &MF) override;70  bool removeSExtWInstrs(MachineFunction &MF, const RISCVInstrInfo &TII,71                         const RISCVSubtarget &ST, MachineRegisterInfo &MRI);72  bool canonicalizeWSuffixes(MachineFunction &MF, const RISCVInstrInfo &TII,73                             const RISCVSubtarget &ST,74                             MachineRegisterInfo &MRI);75 76  void getAnalysisUsage(AnalysisUsage &AU) const override {77    AU.setPreservesCFG();78    MachineFunctionPass::getAnalysisUsage(AU);79  }80 81  StringRef getPassName() const override { return RISCV_OPT_W_INSTRS_NAME; }82};83 84} // end anonymous namespace85 86char RISCVOptWInstrs::ID = 0;87INITIALIZE_PASS(RISCVOptWInstrs, DEBUG_TYPE, RISCV_OPT_W_INSTRS_NAME, false,88                false)89 90FunctionPass *llvm::createRISCVOptWInstrsPass() {91  return new RISCVOptWInstrs();92}93 94static bool vectorPseudoHasAllNBitUsers(const MachineOperand &UserOp,95                                        unsigned Bits) {96  const MachineInstr &MI = *UserOp.getParent();97  unsigned MCOpcode = RISCV::getRVVMCOpcode(MI.getOpcode());98 99  if (!MCOpcode)100    return false;101 102  const MCInstrDesc &MCID = MI.getDesc();103  const uint64_t TSFlags = MCID.TSFlags;104  if (!RISCVII::hasSEWOp(TSFlags))105    return false;106  assert(RISCVII::hasVLOp(TSFlags));107  const unsigned Log2SEW = MI.getOperand(RISCVII::getSEWOpNum(MCID)).getImm();108 109  if (UserOp.getOperandNo() == RISCVII::getVLOpNum(MCID))110    return false;111 112  auto NumDemandedBits =113      RISCV::getVectorLowDemandedScalarBits(MCOpcode, Log2SEW);114  return NumDemandedBits && Bits >= *NumDemandedBits;115}116 117// Checks if all users only demand the lower \p OrigBits of the original118// instruction's result.119// TODO: handle multiple interdependent transformations120static bool hasAllNBitUsers(const MachineInstr &OrigMI,121                            const RISCVSubtarget &ST,122                            const MachineRegisterInfo &MRI, unsigned OrigBits) {123 124  SmallSet<std::pair<const MachineInstr *, unsigned>, 4> Visited;125  SmallVector<std::pair<const MachineInstr *, unsigned>, 4> Worklist;126 127  Worklist.emplace_back(&OrigMI, OrigBits);128 129  while (!Worklist.empty()) {130    auto P = Worklist.pop_back_val();131    const MachineInstr *MI = P.first;132    unsigned Bits = P.second;133 134    if (!Visited.insert(P).second)135      continue;136 137    // Only handle instructions with one def.138    if (MI->getNumExplicitDefs() != 1)139      return false;140 141    Register DestReg = MI->getOperand(0).getReg();142    if (!DestReg.isVirtual())143      return false;144 145    for (auto &UserOp : MRI.use_nodbg_operands(DestReg)) {146      const MachineInstr *UserMI = UserOp.getParent();147      unsigned OpIdx = UserOp.getOperandNo();148 149      switch (UserMI->getOpcode()) {150      default:151        if (vectorPseudoHasAllNBitUsers(UserOp, Bits))152          break;153        return false;154 155      case RISCV::ADDIW:156      case RISCV::ADDW:157      case RISCV::DIVUW:158      case RISCV::DIVW:159      case RISCV::MULW:160      case RISCV::REMUW:161      case RISCV::REMW:162      case RISCV::SLLW:163      case RISCV::SRAIW:164      case RISCV::SRAW:165      case RISCV::SRLIW:166      case RISCV::SRLW:167      case RISCV::SUBW:168      case RISCV::ROLW:169      case RISCV::RORW:170      case RISCV::RORIW:171      case RISCV::CLZW:172      case RISCV::CTZW:173      case RISCV::CPOPW:174      case RISCV::SLLI_UW:175      case RISCV::ABSW:176      case RISCV::FMV_W_X:177      case RISCV::FCVT_H_W:178      case RISCV::FCVT_H_W_INX:179      case RISCV::FCVT_H_WU:180      case RISCV::FCVT_H_WU_INX:181      case RISCV::FCVT_S_W:182      case RISCV::FCVT_S_W_INX:183      case RISCV::FCVT_S_WU:184      case RISCV::FCVT_S_WU_INX:185      case RISCV::FCVT_D_W:186      case RISCV::FCVT_D_W_INX:187      case RISCV::FCVT_D_WU:188      case RISCV::FCVT_D_WU_INX:189        if (Bits >= 32)190          break;191        return false;192 193      case RISCV::SEXT_B:194      case RISCV::PACKH:195        if (Bits >= 8)196          break;197        return false;198      case RISCV::SEXT_H:199      case RISCV::FMV_H_X:200      case RISCV::ZEXT_H_RV32:201      case RISCV::ZEXT_H_RV64:202      case RISCV::PACKW:203        if (Bits >= 16)204          break;205        return false;206 207      case RISCV::PACK:208        if (Bits >= (ST.getXLen() / 2))209          break;210        return false;211 212      case RISCV::SRLI: {213        // If we are shifting right by less than Bits, and users don't demand214        // any bits that were shifted into [Bits-1:0], then we can consider this215        // as an N-Bit user.216        unsigned ShAmt = UserMI->getOperand(2).getImm();217        if (Bits > ShAmt) {218          Worklist.emplace_back(UserMI, Bits - ShAmt);219          break;220        }221        return false;222      }223 224      // these overwrite higher input bits, otherwise the lower word of output225      // depends only on the lower word of input. So check their uses read W.226      case RISCV::SLLI: {227        unsigned ShAmt = UserMI->getOperand(2).getImm();228        if (Bits >= (ST.getXLen() - ShAmt))229          break;230        Worklist.emplace_back(UserMI, Bits + ShAmt);231        break;232      }233      case RISCV::SLLIW: {234        unsigned ShAmt = UserMI->getOperand(2).getImm();235        if (Bits >= 32 - ShAmt)236          break;237        Worklist.emplace_back(UserMI, Bits + ShAmt);238        break;239      }240 241      case RISCV::ANDI: {242        uint64_t Imm = UserMI->getOperand(2).getImm();243        if (Bits >= (unsigned)llvm::bit_width(Imm))244          break;245        Worklist.emplace_back(UserMI, Bits);246        break;247      }248      case RISCV::ORI: {249        uint64_t Imm = UserMI->getOperand(2).getImm();250        if (Bits >= (unsigned)llvm::bit_width<uint64_t>(~Imm))251          break;252        Worklist.emplace_back(UserMI, Bits);253        break;254      }255 256      case RISCV::SLL:257      case RISCV::BSET:258      case RISCV::BCLR:259      case RISCV::BINV:260        // Operand 2 is the shift amount which uses log2(xlen) bits.261        if (OpIdx == 2) {262          if (Bits >= Log2_32(ST.getXLen()))263            break;264          return false;265        }266        Worklist.emplace_back(UserMI, Bits);267        break;268 269      case RISCV::SRA:270      case RISCV::SRL:271      case RISCV::ROL:272      case RISCV::ROR:273        // Operand 2 is the shift amount which uses 6 bits.274        if (OpIdx == 2 && Bits >= Log2_32(ST.getXLen()))275          break;276        return false;277 278      case RISCV::ADD_UW:279      case RISCV::SH1ADD_UW:280      case RISCV::SH2ADD_UW:281      case RISCV::SH3ADD_UW:282        // Operand 1 is implicitly zero extended.283        if (OpIdx == 1 && Bits >= 32)284          break;285        Worklist.emplace_back(UserMI, Bits);286        break;287 288      case RISCV::BEXTI:289        if (UserMI->getOperand(2).getImm() >= Bits)290          return false;291        break;292 293      case RISCV::SB:294        // The first argument is the value to store.295        if (OpIdx == 0 && Bits >= 8)296          break;297        return false;298      case RISCV::SH:299        // The first argument is the value to store.300        if (OpIdx == 0 && Bits >= 16)301          break;302        return false;303      case RISCV::SW:304        // The first argument is the value to store.305        if (OpIdx == 0 && Bits >= 32)306          break;307        return false;308 309      // For these, lower word of output in these operations, depends only on310      // the lower word of input. So, we check all uses only read lower word.311      case RISCV::COPY:312      case RISCV::PHI:313 314      case RISCV::ADD:315      case RISCV::ADDI:316      case RISCV::AND:317      case RISCV::MUL:318      case RISCV::OR:319      case RISCV::SUB:320      case RISCV::XOR:321      case RISCV::XORI:322 323      case RISCV::ANDN:324      case RISCV::CLMUL:325      case RISCV::ORN:326      case RISCV::SH1ADD:327      case RISCV::SH2ADD:328      case RISCV::SH3ADD:329      case RISCV::XNOR:330      case RISCV::BSETI:331      case RISCV::BCLRI:332      case RISCV::BINVI:333        Worklist.emplace_back(UserMI, Bits);334        break;335 336      case RISCV::BREV8:337      case RISCV::ORC_B:338        // BREV8 and ORC_B work on bytes. Round Bits down to the nearest byte.339        Worklist.emplace_back(UserMI, alignDown(Bits, 8));340        break;341 342      case RISCV::PseudoCCMOVGPR:343      case RISCV::PseudoCCMOVGPRNoX0:344        // Either operand 4 or operand 5 is returned by this instruction. If345        // only the lower word of the result is used, then only the lower word346        // of operand 4 and 5 is used.347        if (OpIdx != 4 && OpIdx != 5)348          return false;349        Worklist.emplace_back(UserMI, Bits);350        break;351 352      case RISCV::CZERO_EQZ:353      case RISCV::CZERO_NEZ:354      case RISCV::VT_MASKC:355      case RISCV::VT_MASKCN:356        if (OpIdx != 1)357          return false;358        Worklist.emplace_back(UserMI, Bits);359        break;360      case RISCV::TH_EXT:361      case RISCV::TH_EXTU:362        unsigned Msb = UserMI->getOperand(2).getImm();363        unsigned Lsb = UserMI->getOperand(3).getImm();364        // Behavior of Msb < Lsb is not well documented.365        if (Msb >= Lsb && Bits > Msb)366          break;367        return false;368      }369    }370  }371 372  return true;373}374 375static bool hasAllWUsers(const MachineInstr &OrigMI, const RISCVSubtarget &ST,376                         const MachineRegisterInfo &MRI) {377  return hasAllNBitUsers(OrigMI, ST, MRI, 32);378}379 380// This function returns true if the machine instruction always outputs a value381// where bits 63:32 match bit 31.382static bool isSignExtendingOpW(const MachineInstr &MI, unsigned OpNo) {383  uint64_t TSFlags = MI.getDesc().TSFlags;384 385  // Instructions that can be determined from opcode are marked in tablegen.386  if (TSFlags & RISCVII::IsSignExtendingOpWMask)387    return true;388 389  // Special cases that require checking operands.390  switch (MI.getOpcode()) {391  // shifting right sufficiently makes the value 32-bit sign-extended392  case RISCV::SRAI:393    return MI.getOperand(2).getImm() >= 32;394  case RISCV::SRLI:395    return MI.getOperand(2).getImm() > 32;396  // The LI pattern ADDI rd, X0, imm is sign extended.397  case RISCV::ADDI:398    return MI.getOperand(1).isReg() && MI.getOperand(1).getReg() == RISCV::X0;399  // An ANDI with an 11 bit immediate will zero bits 63:11.400  case RISCV::ANDI:401    return isUInt<11>(MI.getOperand(2).getImm());402  // An ORI with an >11 bit immediate (negative 12-bit) will set bits 63:11.403  case RISCV::ORI:404    return !isUInt<11>(MI.getOperand(2).getImm());405  // A bseti with X0 is sign extended if the immediate is less than 31.406  case RISCV::BSETI:407    return MI.getOperand(2).getImm() < 31 &&408           MI.getOperand(1).getReg() == RISCV::X0;409  // Copying from X0 produces zero.410  case RISCV::COPY:411    return MI.getOperand(1).getReg() == RISCV::X0;412  // Ignore the scratch register destination.413  case RISCV::PseudoAtomicLoadNand32:414    return OpNo == 0;415  case RISCV::PseudoVMV_X_S: {416    // vmv.x.s has at least 33 sign bits if log2(sew) <= 5.417    int64_t Log2SEW = MI.getOperand(2).getImm();418    assert(Log2SEW >= 3 && Log2SEW <= 6 && "Unexpected Log2SEW");419    return Log2SEW <= 5;420  }421  case RISCV::TH_EXT: {422    unsigned Msb = MI.getOperand(2).getImm();423    unsigned Lsb = MI.getOperand(3).getImm();424    return Msb >= Lsb && (Msb - Lsb + 1) <= 32;425  }426  case RISCV::TH_EXTU: {427    unsigned Msb = MI.getOperand(2).getImm();428    unsigned Lsb = MI.getOperand(3).getImm();429    return Msb >= Lsb && (Msb - Lsb + 1) < 32;430  }431  }432 433  return false;434}435 436static bool isSignExtendedW(Register SrcReg, const RISCVSubtarget &ST,437                            const MachineRegisterInfo &MRI,438                            SmallPtrSetImpl<MachineInstr *> &FixableDef) {439  SmallSet<Register, 4> Visited;440  SmallVector<Register, 4> Worklist;441 442  auto AddRegToWorkList = [&](Register SrcReg) {443    if (!SrcReg.isVirtual())444      return false;445    Worklist.push_back(SrcReg);446    return true;447  };448 449  if (!AddRegToWorkList(SrcReg))450    return false;451 452  while (!Worklist.empty()) {453    Register Reg = Worklist.pop_back_val();454 455    // If we already visited this register, we don't need to check it again.456    if (!Visited.insert(Reg).second)457      continue;458 459    MachineInstr *MI = MRI.getVRegDef(Reg);460    if (!MI)461      continue;462 463    int OpNo = MI->findRegisterDefOperandIdx(Reg, /*TRI=*/nullptr);464    assert(OpNo != -1 && "Couldn't find register");465 466    // If this is a sign extending operation we don't need to look any further.467    if (isSignExtendingOpW(*MI, OpNo))468      continue;469 470    // Is this an instruction that propagates sign extend?471    switch (MI->getOpcode()) {472    default:473      // Unknown opcode, give up.474      return false;475    case RISCV::COPY: {476      const MachineFunction *MF = MI->getMF();477      const RISCVMachineFunctionInfo *RVFI =478          MF->getInfo<RISCVMachineFunctionInfo>();479 480      // If this is the entry block and the register is livein, see if we know481      // it is sign extended.482      if (MI->getParent() == &MF->front()) {483        Register VReg = MI->getOperand(0).getReg();484        if (MF->getRegInfo().isLiveIn(VReg) && RVFI->isSExt32Register(VReg))485          continue;486      }487 488      Register CopySrcReg = MI->getOperand(1).getReg();489      if (CopySrcReg == RISCV::X10) {490        // For a method return value, we check the ZExt/SExt flags in attribute.491        // We assume the following code sequence for method call.492        // PseudoCALL @bar, ...493        // ADJCALLSTACKUP 0, 0, implicit-def dead $x2, implicit $x2494        // %0:gpr = COPY $x10495        //496        // We use the PseudoCall to look up the IR function being called to find497        // its return attributes.498        const MachineBasicBlock *MBB = MI->getParent();499        auto II = MI->getIterator();500        if (II == MBB->instr_begin() ||501            (--II)->getOpcode() != RISCV::ADJCALLSTACKUP)502          return false;503 504        const MachineInstr &CallMI = *(--II);505        if (!CallMI.isCall() || !CallMI.getOperand(0).isGlobal())506          return false;507 508        auto *CalleeFn =509            dyn_cast_if_present<Function>(CallMI.getOperand(0).getGlobal());510        if (!CalleeFn)511          return false;512 513        auto *IntTy = dyn_cast<IntegerType>(CalleeFn->getReturnType());514        if (!IntTy)515          return false;516 517        const AttributeSet &Attrs = CalleeFn->getAttributes().getRetAttrs();518        unsigned BitWidth = IntTy->getBitWidth();519        if ((BitWidth <= 32 && Attrs.hasAttribute(Attribute::SExt)) ||520            (BitWidth < 32 && Attrs.hasAttribute(Attribute::ZExt)))521          continue;522      }523 524      if (!AddRegToWorkList(CopySrcReg))525        return false;526 527      break;528    }529 530    // For these, we just need to check if the 1st operand is sign extended.531    case RISCV::BCLRI:532    case RISCV::BINVI:533    case RISCV::BSETI:534      if (MI->getOperand(2).getImm() >= 31)535        return false;536      [[fallthrough]];537    case RISCV::REM:538    case RISCV::ANDI:539    case RISCV::ORI:540    case RISCV::XORI:541    case RISCV::SRAI:542      // |Remainder| is always <= |Dividend|. If D is 32-bit, then so is R.543      // DIV doesn't work because of the edge case 0xf..f 8000 0000 / (long)-1544      // Logical operations use a sign extended 12-bit immediate.545      // Arithmetic shift right can only increase the number of sign bits.546      if (!AddRegToWorkList(MI->getOperand(1).getReg()))547        return false;548 549      break;550    case RISCV::PseudoCCADDW:551    case RISCV::PseudoCCADDIW:552    case RISCV::PseudoCCSUBW:553    case RISCV::PseudoCCSLLW:554    case RISCV::PseudoCCSRLW:555    case RISCV::PseudoCCSRAW:556    case RISCV::PseudoCCSLLIW:557    case RISCV::PseudoCCSRLIW:558    case RISCV::PseudoCCSRAIW:559      // Returns operand 4 or an ADDW/SUBW/etc. of operands 5 and 6. We only560      // need to check if operand 4 is sign extended.561      if (!AddRegToWorkList(MI->getOperand(4).getReg()))562        return false;563      break;564    case RISCV::REMU:565    case RISCV::AND:566    case RISCV::OR:567    case RISCV::XOR:568    case RISCV::ANDN:569    case RISCV::ORN:570    case RISCV::XNOR:571    case RISCV::MAX:572    case RISCV::MAXU:573    case RISCV::MIN:574    case RISCV::MINU:575    case RISCV::PseudoCCMOVGPR:576    case RISCV::PseudoCCMOVGPRNoX0:577    case RISCV::PseudoCCAND:578    case RISCV::PseudoCCOR:579    case RISCV::PseudoCCXOR:580    case RISCV::PseudoCCANDN:581    case RISCV::PseudoCCORN:582    case RISCV::PseudoCCXNOR:583    case RISCV::PHI: {584      // If all incoming values are sign-extended, the output of AND, OR, XOR,585      // MIN, MAX, or PHI is also sign-extended.586 587      // The input registers for PHI are operand 1, 3, ...588      // The input registers for PseudoCCMOVGPR(NoX0) are 4 and 5.589      // The input registers for PseudoCCAND/OR/XOR are 4, 5, and 6.590      // The input registers for others are operand 1 and 2.591      unsigned B = 1, E = 3, D = 1;592      switch (MI->getOpcode()) {593      case RISCV::PHI:594        E = MI->getNumOperands();595        D = 2;596        break;597      case RISCV::PseudoCCMOVGPR:598      case RISCV::PseudoCCMOVGPRNoX0:599        B = 4;600        E = 6;601        break;602      case RISCV::PseudoCCAND:603      case RISCV::PseudoCCOR:604      case RISCV::PseudoCCXOR:605      case RISCV::PseudoCCANDN:606      case RISCV::PseudoCCORN:607      case RISCV::PseudoCCXNOR:608        B = 4;609        E = 7;610        break;611       }612 613      for (unsigned I = B; I != E; I += D) {614        if (!MI->getOperand(I).isReg())615          return false;616 617        if (!AddRegToWorkList(MI->getOperand(I).getReg()))618          return false;619      }620 621      break;622    }623 624    case RISCV::CZERO_EQZ:625    case RISCV::CZERO_NEZ:626    case RISCV::VT_MASKC:627    case RISCV::VT_MASKCN:628      // Instructions return zero or operand 1. Result is sign extended if629      // operand 1 is sign extended.630      if (!AddRegToWorkList(MI->getOperand(1).getReg()))631        return false;632      break;633 634    case RISCV::ADDI: {635      if (MI->getOperand(1).isReg() && MI->getOperand(1).getReg().isVirtual()) {636        if (MachineInstr *SrcMI = MRI.getVRegDef(MI->getOperand(1).getReg())) {637          if (SrcMI->getOpcode() == RISCV::LUI &&638              SrcMI->getOperand(1).isImm()) {639            uint64_t Imm = SrcMI->getOperand(1).getImm();640            Imm = SignExtend64<32>(Imm << 12);641            Imm += (uint64_t)MI->getOperand(2).getImm();642            if (isInt<32>(Imm))643              continue;644          }645        }646      }647 648      if (hasAllWUsers(*MI, ST, MRI)) {649        FixableDef.insert(MI);650        break;651      }652      return false;653    }654 655    // With these opcode, we can "fix" them with the W-version656    // if we know all users of the result only rely on bits 31:0657    case RISCV::SLLI:658      // SLLIW reads the lowest 5 bits, while SLLI reads lowest 6 bits659      if (MI->getOperand(2).getImm() >= 32)660        return false;661      [[fallthrough]];662    case RISCV::ADD:663    case RISCV::LD:664    case RISCV::LWU:665    case RISCV::MUL:666    case RISCV::SUB:667      if (hasAllWUsers(*MI, ST, MRI)) {668        FixableDef.insert(MI);669        break;670      }671      return false;672    }673  }674 675  // If we get here, then every node we visited produces a sign extended value676  // or propagated sign extended values. So the result must be sign extended.677  return true;678}679 680static unsigned getWOp(unsigned Opcode) {681  switch (Opcode) {682  case RISCV::ADDI:683    return RISCV::ADDIW;684  case RISCV::ADD:685    return RISCV::ADDW;686  case RISCV::LD:687  case RISCV::LWU:688    return RISCV::LW;689  case RISCV::MUL:690    return RISCV::MULW;691  case RISCV::SLLI:692    return RISCV::SLLIW;693  case RISCV::SUB:694    return RISCV::SUBW;695  default:696    llvm_unreachable("Unexpected opcode for replacement with W variant");697  }698}699 700bool RISCVOptWInstrs::removeSExtWInstrs(MachineFunction &MF,701                                        const RISCVInstrInfo &TII,702                                        const RISCVSubtarget &ST,703                                        MachineRegisterInfo &MRI) {704  if (DisableSExtWRemoval)705    return false;706 707  bool MadeChange = false;708  for (MachineBasicBlock &MBB : MF) {709    for (MachineInstr &MI : llvm::make_early_inc_range(MBB)) {710      // We're looking for the sext.w pattern ADDIW rd, rs1, 0.711      if (!RISCVInstrInfo::isSEXT_W(MI))712        continue;713 714      Register SrcReg = MI.getOperand(1).getReg();715 716      SmallPtrSet<MachineInstr *, 4> FixableDefs;717 718      // If all users only use the lower bits, this sext.w is redundant.719      // Or if all definitions reaching MI sign-extend their output,720      // then sext.w is redundant.721      if (!hasAllWUsers(MI, ST, MRI) &&722          !isSignExtendedW(SrcReg, ST, MRI, FixableDefs))723        continue;724 725      Register DstReg = MI.getOperand(0).getReg();726      if (!MRI.constrainRegClass(SrcReg, MRI.getRegClass(DstReg)))727        continue;728 729      // Convert Fixable instructions to their W versions.730      for (MachineInstr *Fixable : FixableDefs) {731        LLVM_DEBUG(dbgs() << "Replacing " << *Fixable);732        Fixable->setDesc(TII.get(getWOp(Fixable->getOpcode())));733        Fixable->clearFlag(MachineInstr::MIFlag::NoSWrap);734        Fixable->clearFlag(MachineInstr::MIFlag::NoUWrap);735        Fixable->clearFlag(MachineInstr::MIFlag::IsExact);736        LLVM_DEBUG(dbgs() << "     with " << *Fixable);737        ++NumTransformedToWInstrs;738      }739 740      LLVM_DEBUG(dbgs() << "Removing redundant sign-extension\n");741      MRI.replaceRegWith(DstReg, SrcReg);742      MRI.clearKillFlags(SrcReg);743      MI.eraseFromParent();744      ++NumRemovedSExtW;745      MadeChange = true;746    }747  }748 749  return MadeChange;750}751 752// Strips or adds W suffixes to eligible instructions depending on the753// subtarget preferences.754bool RISCVOptWInstrs::canonicalizeWSuffixes(MachineFunction &MF,755                                            const RISCVInstrInfo &TII,756                                            const RISCVSubtarget &ST,757                                            MachineRegisterInfo &MRI) {758  bool ShouldStripW = !(DisableStripWSuffix || ST.preferWInst());759  bool ShouldPreferW = ST.preferWInst();760  bool MadeChange = false;761 762  for (MachineBasicBlock &MBB : MF) {763    for (MachineInstr &MI : MBB) {764      std::optional<unsigned> WOpc;765      std::optional<unsigned> NonWOpc;766      unsigned OrigOpc = MI.getOpcode();767      switch (OrigOpc) {768      default:769        continue;770      case RISCV::ADDW:771        NonWOpc = RISCV::ADD;772        break;773      case RISCV::ADDIW:774        NonWOpc = RISCV::ADDI;775        break;776      case RISCV::MULW:777        NonWOpc = RISCV::MUL;778        break;779      case RISCV::SLLIW:780        NonWOpc = RISCV::SLLI;781        break;782      case RISCV::SUBW:783        NonWOpc = RISCV::SUB;784        break;785      case RISCV::ADD:786        WOpc = RISCV::ADDW;787        break;788      case RISCV::ADDI:789        WOpc = RISCV::ADDIW;790        break;791      case RISCV::SUB:792        WOpc = RISCV::SUBW;793        break;794      case RISCV::MUL:795        WOpc = RISCV::MULW;796        break;797      case RISCV::SLLI:798        // SLLIW reads the lowest 5 bits, while SLLI reads lowest 6 bits.799        if (MI.getOperand(2).getImm() >= 32)800          continue;801        WOpc = RISCV::SLLIW;802        break;803      case RISCV::LD:804      case RISCV::LWU:805        WOpc = RISCV::LW;806        break;807      }808 809      if (ShouldStripW && NonWOpc.has_value() && hasAllWUsers(MI, ST, MRI)) {810        LLVM_DEBUG(dbgs() << "Replacing " << MI);811        MI.setDesc(TII.get(NonWOpc.value()));812        LLVM_DEBUG(dbgs() << "     with " << MI);813        ++NumTransformedToNonWInstrs;814        MadeChange = true;815        continue;816      }817      // LWU is always converted to LW when possible as 1) LW is compressible818      // and 2) it helps minimise differences vs RV32.819      if ((ShouldPreferW || OrigOpc == RISCV::LWU) && WOpc.has_value() &&820          hasAllWUsers(MI, ST, MRI)) {821        LLVM_DEBUG(dbgs() << "Replacing " << MI);822        MI.setDesc(TII.get(WOpc.value()));823        MI.clearFlag(MachineInstr::MIFlag::NoSWrap);824        MI.clearFlag(MachineInstr::MIFlag::NoUWrap);825        MI.clearFlag(MachineInstr::MIFlag::IsExact);826        LLVM_DEBUG(dbgs() << "     with " << MI);827        ++NumTransformedToWInstrs;828        MadeChange = true;829        continue;830      }831    }832  }833  return MadeChange;834}835 836bool RISCVOptWInstrs::runOnMachineFunction(MachineFunction &MF) {837  if (skipFunction(MF.getFunction()))838    return false;839 840  MachineRegisterInfo &MRI = MF.getRegInfo();841  const RISCVSubtarget &ST = MF.getSubtarget<RISCVSubtarget>();842  const RISCVInstrInfo &TII = *ST.getInstrInfo();843 844  if (!ST.is64Bit())845    return false;846 847  bool MadeChange = false;848  MadeChange |= removeSExtWInstrs(MF, TII, ST, MRI);849  MadeChange |= canonicalizeWSuffixes(MF, TII, ST, MRI);850  return MadeChange;851}852