45#define DEBUG_TYPE "riscv-opt-w-instrs" 
   46#define RISCV_OPT_W_INSTRS_NAME "RISC-V Optimize W Instructions" 
   48STATISTIC(NumRemovedSExtW, 
"Number of removed sign-extensions");
 
   50          "Number of instructions transformed to W-ops");
 
   52          "Number of instructions transformed to non-W-ops");
 
   55                                         cl::desc(
"Disable removal of sext.w"),
 
   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);
 
   76  void getAnalysisUsage(AnalysisUsage &AU)
 const override {
 
   86char RISCVOptWInstrs::ID = 0;
 
   91  return new RISCVOptWInstrs();
 
 
  112  auto NumDemandedBits =
 
  114  return NumDemandedBits && Bits >= *NumDemandedBits;
 
 
  129  while (!Worklist.
empty()) {
 
  132    unsigned Bits = 
P.second;
 
  138    if (
MI->getNumExplicitDefs() != 1)
 
  141    Register DestReg = 
MI->getOperand(0).getReg();
 
  145    for (
auto &UserOp : 
MRI.use_nodbg_operands(DestReg)) {
 
  147      unsigned OpIdx = UserOp.getOperandNo();
 
  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:
 
  200      case RISCV::ZEXT_H_RV32:
 
  201      case RISCV::ZEXT_H_RV64:
 
  208        if (Bits >= (ST.getXLen() / 2))
 
  228        if (Bits >= (ST.getXLen() - ShAmt))
 
  235        if (Bits >= 32 - ShAmt)
 
  262          if (Bits >= 
Log2_32(ST.getXLen()))
 
  279      case RISCV::SH1ADD_UW:
 
  280      case RISCV::SH2ADD_UW:
 
  281      case RISCV::SH3ADD_UW:
 
  283        if (
OpIdx == 1 && Bits >= 32)
 
  295        if (
OpIdx == 0 && Bits >= 8)
 
  300        if (
OpIdx == 0 && Bits >= 16)
 
  305        if (
OpIdx == 0 && Bits >= 32)
 
  342      case RISCV::PseudoCCMOVGPR:
 
  343      case RISCV::PseudoCCMOVGPRNoX0:
 
  352      case RISCV::CZERO_EQZ:
 
  353      case RISCV::CZERO_NEZ:
 
  354      case RISCV::VT_MASKC:
 
  355      case RISCV::VT_MASKCN:
 
  365        if (Msb >= Lsb && Bits > Msb)
 
 
  390  switch (
MI.getOpcode()) {
 
  393    return MI.getOperand(2).getImm() >= 32;
 
  395    return MI.getOperand(2).getImm() > 32;
 
  398    return MI.getOperand(1).isReg() && 
MI.getOperand(1).getReg() == RISCV::X0;
 
  407    return MI.getOperand(2).getImm() < 31 &&
 
  408           MI.getOperand(1).getReg() == RISCV::X0;
 
  411    return MI.getOperand(1).getReg() == RISCV::X0;
 
  413  case RISCV::PseudoAtomicLoadNand32:
 
  415  case RISCV::PseudoVMV_X_S: {
 
  417    int64_t Log2SEW = 
MI.getOperand(2).getImm();
 
  418    assert(Log2SEW >= 3 && Log2SEW <= 6 && 
"Unexpected Log2SEW");
 
  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;
 
  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;
 
 
  442  auto AddRegToWorkList = [&](
Register SrcReg) {
 
  449  if (!AddRegToWorkList(SrcReg))
 
  452  while (!Worklist.
empty()) {
 
  463    int OpNo = 
MI->findRegisterDefOperandIdx(
Reg, 
nullptr);
 
  464    assert(OpNo != -1 && 
"Couldn't find register");
 
  471    switch (
MI->getOpcode()) {
 
  482      if (
MI->getParent() == &MF->
front()) {
 
  488      Register CopySrcReg = 
MI->getOperand(1).getReg();
 
  489      if (CopySrcReg == RISCV::X10) {
 
  499        auto II = 
MI->getIterator();
 
  500        if (
II == 
MBB->instr_begin() ||
 
  501            (--
II)->getOpcode() != RISCV::ADJCALLSTACKUP)
 
  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)))
 
  524      if (!AddRegToWorkList(CopySrcReg))
 
  534      if (
MI->getOperand(2).getImm() >= 31)
 
  546      if (!AddRegToWorkList(
MI->getOperand(1).getReg()))
 
  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:
 
  561      if (!AddRegToWorkList(
MI->getOperand(4).getReg()))
 
  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:
 
  591      unsigned B = 1, 
E = 3, 
D = 1;
 
  592      switch (
MI->getOpcode()) {
 
  594        E = 
MI->getNumOperands();
 
  597      case RISCV::PseudoCCMOVGPR:
 
  598      case RISCV::PseudoCCMOVGPRNoX0:
 
  602      case RISCV::PseudoCCAND:
 
  603      case RISCV::PseudoCCOR:
 
  604      case RISCV::PseudoCCXOR:
 
  605      case RISCV::PseudoCCANDN:
 
  606      case RISCV::PseudoCCORN:
 
  607      case RISCV::PseudoCCXNOR:
 
  613      for (
unsigned I = 
B; 
I != 
E; 
I += 
D) {
 
  614        if (!
MI->getOperand(
I).isReg())
 
  617        if (!AddRegToWorkList(
MI->getOperand(
I).getReg()))
 
  624    case RISCV::CZERO_EQZ:
 
  625    case RISCV::CZERO_NEZ:
 
  626    case RISCV::VT_MASKC:
 
  627    case RISCV::VT_MASKCN:
 
  630      if (!AddRegToWorkList(
MI->getOperand(1).getReg()))
 
  635      if (
MI->getOperand(1).isReg() && 
MI->getOperand(1).getReg().isVirtual()) {
 
  637          if (SrcMI->getOpcode() == RISCV::LUI &&
 
  638              SrcMI->getOperand(1).isImm()) {
 
  639            uint64_t Imm = SrcMI->getOperand(1).getImm();
 
  659      if (
MI->getOperand(2).getImm() >= 32)
 
 
  707  bool MadeChange = 
false;
 
  708  for (MachineBasicBlock &
MBB : MF) {
 
  711      if (!RISCVInstrInfo::isSEXT_W(
MI))
 
  716      SmallPtrSet<MachineInstr *, 4> FixableDefs;
 
  726      if (!
MRI.constrainRegClass(SrcReg, 
MRI.getRegClass(DstReg)))
 
  730      for (MachineInstr *Fixable : FixableDefs) {
 
  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);
 
  737        ++NumTransformedToWInstrs;
 
  741      MRI.replaceRegWith(DstReg, SrcReg);
 
  742      MRI.clearKillFlags(SrcReg);
 
  743      MI.eraseFromParent();
 
  754bool RISCVOptWInstrs::canonicalizeWSuffixes(MachineFunction &MF,
 
  755                                            const RISCVInstrInfo &
TII,
 
  756                                            const RISCVSubtarget &ST,
 
  757                                            MachineRegisterInfo &
MRI) {
 
  759  bool ShouldPreferW = 
ST.preferWInst();
 
  760  bool MadeChange = 
false;
 
  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();
 
  771        NonWOpc = RISCV::ADD;
 
  774        NonWOpc = RISCV::ADDI;
 
  777        NonWOpc = RISCV::MUL;
 
  780        NonWOpc = RISCV::SLLI;
 
  783        NonWOpc = RISCV::SUB;
 
  799        if (
MI.getOperand(2).getImm() >= 32)
 
  811        MI.setDesc(
TII.get(NonWOpc.value()));
 
  813        ++NumTransformedToNonWInstrs;
 
  819      if ((ShouldPreferW || OrigOpc == RISCV::LWU) && WOpc.has_value() &&
 
  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);
 
  827        ++NumTransformedToWInstrs;
 
  836bool RISCVOptWInstrs::runOnMachineFunction(MachineFunction &MF) {
 
  842  const RISCVInstrInfo &
TII = *
ST.getInstrInfo();
 
  847  bool MadeChange = 
false;
 
  848  MadeChange |= removeSExtWInstrs(MF, 
TII, ST, 
MRI);
 
  849  MadeChange |= canonicalizeWSuffixes(MF, 
TII, ST, 
MRI);
 
unsigned const MachineRegisterInfo * MRI
 
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
 
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
 
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
 
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
 
const HexagonInstrInfo * TII
 
static cl::opt< bool > DisableSExtWRemoval("loongarch-disable-sextw-removal", cl::desc("Disable removal of sign-extend insn"), cl::init(false), cl::Hidden)
 
static bool hasAllWUsers(const MachineInstr &OrigMI, const LoongArchSubtarget &ST, const MachineRegisterInfo &MRI)
 
static bool isSignExtendedW(Register SrcReg, const LoongArchSubtarget &ST, const MachineRegisterInfo &MRI, SmallPtrSetImpl< MachineInstr * > &FixableDef)
 
static unsigned getWOp(unsigned Opcode)
 
Promote Memory to Register
 
MachineInstr unsigned OpIdx
 
uint64_t IntrinsicInst * II
 
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
 
static bool isSignExtendedW(Register SrcReg, const RISCVSubtarget &ST, const MachineRegisterInfo &MRI, SmallPtrSetImpl< MachineInstr * > &FixableDef)
 
static bool hasAllWUsers(const MachineInstr &OrigMI, const RISCVSubtarget &ST, const MachineRegisterInfo &MRI)
 
static bool isSignExtendingOpW(const MachineInstr &MI, unsigned OpNo)
 
static cl::opt< bool > DisableStripWSuffix("riscv-disable-strip-w-suffix", cl::desc("Disable strip W suffix"), cl::init(false), cl::Hidden)
 
static bool hasAllNBitUsers(const MachineInstr &OrigMI, const RISCVSubtarget &ST, const MachineRegisterInfo &MRI, unsigned OrigBits)
 
#define RISCV_OPT_W_INSTRS_NAME
 
static bool vectorPseudoHasAllNBitUsers(const MachineOperand &UserOp, unsigned Bits)
 
static cl::opt< bool > DisableSExtWRemoval("riscv-disable-sextw-removal", cl::desc("Disable removal of sext.w"), cl::init(false), cl::Hidden)
 
static unsigned getWOp(unsigned Opcode)
 
This file defines the SmallSet class.
 
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
 
#define STATISTIC(VARNAME, DESC)
 
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
 
This class holds the attributes for a particular argument, parameter, function, or return value.
 
FunctionPass class - This class is used to implement most global optimizations.
 
Describe properties that are true of each instruction in the target description file.
 
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
 
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
 
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
 
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
 
Function & getFunction()
Return the LLVM function that this machine code represents.
 
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
 
const MachineBasicBlock & front() const
 
Representation of each machine instruction.
 
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
 
const MachineBasicBlock * getParent() const
 
bool isCall(QueryType Type=AnyInBundle) const
 
const MachineOperand & getOperand(unsigned i) const
 
MachineOperand class - Representation of each machine instruction operand.
 
LLVM_ABI unsigned getOperandNo() const
Returns the index of this operand in the instruction that it belongs to.
 
const GlobalValue * getGlobal() const
 
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
 
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
 
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
 
LLVM_ABI bool isLiveIn(Register Reg) const
 
RISCVMachineFunctionInfo - This class is derived from MachineFunctionInfo and contains private RISCV-...
 
bool isSExt32Register(Register Reg) const
 
Wrapper class representing virtual and physical registers.
 
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
 
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
 
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
 
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
 
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
 
reference emplace_back(ArgTypes &&... Args)
 
void push_back(const T &Elt)
 
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
 
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
 
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
 
static unsigned getVLOpNum(const MCInstrDesc &Desc)
 
static bool hasVLOp(uint64_t TSFlags)
 
static unsigned getSEWOpNum(const MCInstrDesc &Desc)
 
static bool hasSEWOp(uint64_t TSFlags)
 
unsigned getRVVMCOpcode(unsigned RVVPseudoOpcode)
 
std::optional< unsigned > getVectorLowDemandedScalarBits(unsigned Opcode, unsigned Log2SEW)
 
initializer< Ty > init(const Ty &Val)
 
This is an optimization pass for GlobalISel generic memory operations.
 
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
 
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
 
auto dyn_cast_if_present(const Y &Val)
dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a null (or none in the case ...
 
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
 
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
 
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
 
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
 
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
 
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
 
FunctionPass * createRISCVOptWInstrsPass()
 
constexpr unsigned BitWidth
 
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.