106c3fb27SDimitry Andric //===- RISCVOptWInstrs.cpp - MI W instruction optimizations ---------------===// 206c3fb27SDimitry Andric // 306c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 406c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 506c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 606c3fb27SDimitry Andric // 706c3fb27SDimitry Andric //===---------------------------------------------------------------------===// 806c3fb27SDimitry Andric // 906c3fb27SDimitry Andric // This pass does some optimizations for *W instructions at the MI level. 1006c3fb27SDimitry Andric // 1106c3fb27SDimitry Andric // First it removes unneeded sext.w instructions. Either because the sign 1206c3fb27SDimitry Andric // extended bits aren't consumed or because the input was already sign extended 1306c3fb27SDimitry Andric // by an earlier instruction. 1406c3fb27SDimitry Andric // 155f757f3fSDimitry Andric // Then it removes the -w suffix from opw instructions whenever all users are 165f757f3fSDimitry Andric // dependent only on the lower word of the result of the instruction. 175f757f3fSDimitry Andric // The cases handled are: 185f757f3fSDimitry Andric // * addw because c.add has a larger register encoding than c.addw. 195f757f3fSDimitry Andric // * addiw because it helps reduce test differences between RV32 and RV64 205f757f3fSDimitry Andric // w/o being a pessimization. 215f757f3fSDimitry Andric // * mulw because c.mulw doesn't exist but c.mul does (w/ zcb) 225f757f3fSDimitry Andric // * slliw because c.slliw doesn't exist and c.slli does 2306c3fb27SDimitry Andric // 2406c3fb27SDimitry Andric //===---------------------------------------------------------------------===// 2506c3fb27SDimitry Andric 2606c3fb27SDimitry Andric #include "RISCV.h" 2706c3fb27SDimitry Andric #include "RISCVMachineFunctionInfo.h" 2806c3fb27SDimitry Andric #include "RISCVSubtarget.h" 295f757f3fSDimitry Andric #include "llvm/ADT/SmallSet.h" 3006c3fb27SDimitry Andric #include "llvm/ADT/Statistic.h" 3106c3fb27SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 3206c3fb27SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h" 3306c3fb27SDimitry Andric 3406c3fb27SDimitry Andric using namespace llvm; 3506c3fb27SDimitry Andric 3606c3fb27SDimitry Andric #define DEBUG_TYPE "riscv-opt-w-instrs" 3706c3fb27SDimitry Andric #define RISCV_OPT_W_INSTRS_NAME "RISC-V Optimize W Instructions" 3806c3fb27SDimitry Andric 3906c3fb27SDimitry Andric STATISTIC(NumRemovedSExtW, "Number of removed sign-extensions"); 4006c3fb27SDimitry Andric STATISTIC(NumTransformedToWInstrs, 4106c3fb27SDimitry Andric "Number of instructions transformed to W-ops"); 4206c3fb27SDimitry Andric 4306c3fb27SDimitry Andric static cl::opt<bool> DisableSExtWRemoval("riscv-disable-sextw-removal", 4406c3fb27SDimitry Andric cl::desc("Disable removal of sext.w"), 4506c3fb27SDimitry Andric cl::init(false), cl::Hidden); 4606c3fb27SDimitry Andric static cl::opt<bool> DisableStripWSuffix("riscv-disable-strip-w-suffix", 4706c3fb27SDimitry Andric cl::desc("Disable strip W suffix"), 4806c3fb27SDimitry Andric cl::init(false), cl::Hidden); 4906c3fb27SDimitry Andric 5006c3fb27SDimitry Andric namespace { 5106c3fb27SDimitry Andric 5206c3fb27SDimitry Andric class RISCVOptWInstrs : public MachineFunctionPass { 5306c3fb27SDimitry Andric public: 5406c3fb27SDimitry Andric static char ID; 5506c3fb27SDimitry Andric 565f757f3fSDimitry Andric RISCVOptWInstrs() : MachineFunctionPass(ID) {} 5706c3fb27SDimitry Andric 5806c3fb27SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override; 5906c3fb27SDimitry Andric bool removeSExtWInstrs(MachineFunction &MF, const RISCVInstrInfo &TII, 6006c3fb27SDimitry Andric const RISCVSubtarget &ST, MachineRegisterInfo &MRI); 6106c3fb27SDimitry Andric bool stripWSuffixes(MachineFunction &MF, const RISCVInstrInfo &TII, 6206c3fb27SDimitry Andric const RISCVSubtarget &ST, MachineRegisterInfo &MRI); 6306c3fb27SDimitry Andric 6406c3fb27SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 6506c3fb27SDimitry Andric AU.setPreservesCFG(); 6606c3fb27SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 6706c3fb27SDimitry Andric } 6806c3fb27SDimitry Andric 6906c3fb27SDimitry Andric StringRef getPassName() const override { return RISCV_OPT_W_INSTRS_NAME; } 7006c3fb27SDimitry Andric }; 7106c3fb27SDimitry Andric 7206c3fb27SDimitry Andric } // end anonymous namespace 7306c3fb27SDimitry Andric 7406c3fb27SDimitry Andric char RISCVOptWInstrs::ID = 0; 7506c3fb27SDimitry Andric INITIALIZE_PASS(RISCVOptWInstrs, DEBUG_TYPE, RISCV_OPT_W_INSTRS_NAME, false, 7606c3fb27SDimitry Andric false) 7706c3fb27SDimitry Andric 7806c3fb27SDimitry Andric FunctionPass *llvm::createRISCVOptWInstrsPass() { 7906c3fb27SDimitry Andric return new RISCVOptWInstrs(); 8006c3fb27SDimitry Andric } 8106c3fb27SDimitry Andric 825f757f3fSDimitry Andric static bool vectorPseudoHasAllNBitUsers(const MachineOperand &UserOp, 835f757f3fSDimitry Andric unsigned Bits) { 845f757f3fSDimitry Andric const MachineInstr &MI = *UserOp.getParent(); 855f757f3fSDimitry Andric unsigned MCOpcode = RISCV::getRVVMCOpcode(MI.getOpcode()); 865f757f3fSDimitry Andric 875f757f3fSDimitry Andric if (!MCOpcode) 885f757f3fSDimitry Andric return false; 895f757f3fSDimitry Andric 905f757f3fSDimitry Andric const MCInstrDesc &MCID = MI.getDesc(); 915f757f3fSDimitry Andric const uint64_t TSFlags = MCID.TSFlags; 925f757f3fSDimitry Andric if (!RISCVII::hasSEWOp(TSFlags)) 935f757f3fSDimitry Andric return false; 945f757f3fSDimitry Andric assert(RISCVII::hasVLOp(TSFlags)); 955f757f3fSDimitry Andric const unsigned Log2SEW = MI.getOperand(RISCVII::getSEWOpNum(MCID)).getImm(); 965f757f3fSDimitry Andric 975f757f3fSDimitry Andric if (UserOp.getOperandNo() == RISCVII::getVLOpNum(MCID)) 985f757f3fSDimitry Andric return false; 995f757f3fSDimitry Andric 1005f757f3fSDimitry Andric auto NumDemandedBits = 1015f757f3fSDimitry Andric RISCV::getVectorLowDemandedScalarBits(MCOpcode, Log2SEW); 1025f757f3fSDimitry Andric return NumDemandedBits && Bits >= *NumDemandedBits; 1035f757f3fSDimitry Andric } 1045f757f3fSDimitry Andric 10506c3fb27SDimitry Andric // Checks if all users only demand the lower \p OrigBits of the original 10606c3fb27SDimitry Andric // instruction's result. 10706c3fb27SDimitry Andric // TODO: handle multiple interdependent transformations 10806c3fb27SDimitry Andric static bool hasAllNBitUsers(const MachineInstr &OrigMI, 10906c3fb27SDimitry Andric const RISCVSubtarget &ST, 11006c3fb27SDimitry Andric const MachineRegisterInfo &MRI, unsigned OrigBits) { 11106c3fb27SDimitry Andric 11206c3fb27SDimitry Andric SmallSet<std::pair<const MachineInstr *, unsigned>, 4> Visited; 11306c3fb27SDimitry Andric SmallVector<std::pair<const MachineInstr *, unsigned>, 4> Worklist; 11406c3fb27SDimitry Andric 11506c3fb27SDimitry Andric Worklist.push_back(std::make_pair(&OrigMI, OrigBits)); 11606c3fb27SDimitry Andric 11706c3fb27SDimitry Andric while (!Worklist.empty()) { 11806c3fb27SDimitry Andric auto P = Worklist.pop_back_val(); 11906c3fb27SDimitry Andric const MachineInstr *MI = P.first; 12006c3fb27SDimitry Andric unsigned Bits = P.second; 12106c3fb27SDimitry Andric 12206c3fb27SDimitry Andric if (!Visited.insert(P).second) 12306c3fb27SDimitry Andric continue; 12406c3fb27SDimitry Andric 12506c3fb27SDimitry Andric // Only handle instructions with one def. 12606c3fb27SDimitry Andric if (MI->getNumExplicitDefs() != 1) 12706c3fb27SDimitry Andric return false; 12806c3fb27SDimitry Andric 1291db9f3b2SDimitry Andric Register DestReg = MI->getOperand(0).getReg(); 1301db9f3b2SDimitry Andric if (!DestReg.isVirtual()) 1311db9f3b2SDimitry Andric return false; 1321db9f3b2SDimitry Andric 1331db9f3b2SDimitry Andric for (auto &UserOp : MRI.use_nodbg_operands(DestReg)) { 13406c3fb27SDimitry Andric const MachineInstr *UserMI = UserOp.getParent(); 13506c3fb27SDimitry Andric unsigned OpIdx = UserOp.getOperandNo(); 13606c3fb27SDimitry Andric 13706c3fb27SDimitry Andric switch (UserMI->getOpcode()) { 13806c3fb27SDimitry Andric default: 1395f757f3fSDimitry Andric if (vectorPseudoHasAllNBitUsers(UserOp, Bits)) 1405f757f3fSDimitry Andric break; 14106c3fb27SDimitry Andric return false; 14206c3fb27SDimitry Andric 14306c3fb27SDimitry Andric case RISCV::ADDIW: 14406c3fb27SDimitry Andric case RISCV::ADDW: 14506c3fb27SDimitry Andric case RISCV::DIVUW: 14606c3fb27SDimitry Andric case RISCV::DIVW: 14706c3fb27SDimitry Andric case RISCV::MULW: 14806c3fb27SDimitry Andric case RISCV::REMUW: 14906c3fb27SDimitry Andric case RISCV::REMW: 15006c3fb27SDimitry Andric case RISCV::SLLIW: 15106c3fb27SDimitry Andric case RISCV::SLLW: 15206c3fb27SDimitry Andric case RISCV::SRAIW: 15306c3fb27SDimitry Andric case RISCV::SRAW: 15406c3fb27SDimitry Andric case RISCV::SRLIW: 15506c3fb27SDimitry Andric case RISCV::SRLW: 15606c3fb27SDimitry Andric case RISCV::SUBW: 15706c3fb27SDimitry Andric case RISCV::ROLW: 15806c3fb27SDimitry Andric case RISCV::RORW: 15906c3fb27SDimitry Andric case RISCV::RORIW: 16006c3fb27SDimitry Andric case RISCV::CLZW: 16106c3fb27SDimitry Andric case RISCV::CTZW: 16206c3fb27SDimitry Andric case RISCV::CPOPW: 16306c3fb27SDimitry Andric case RISCV::SLLI_UW: 16406c3fb27SDimitry Andric case RISCV::FMV_W_X: 16506c3fb27SDimitry Andric case RISCV::FCVT_H_W: 16606c3fb27SDimitry Andric case RISCV::FCVT_H_WU: 16706c3fb27SDimitry Andric case RISCV::FCVT_S_W: 16806c3fb27SDimitry Andric case RISCV::FCVT_S_WU: 16906c3fb27SDimitry Andric case RISCV::FCVT_D_W: 17006c3fb27SDimitry Andric case RISCV::FCVT_D_WU: 17106c3fb27SDimitry Andric if (Bits >= 32) 17206c3fb27SDimitry Andric break; 17306c3fb27SDimitry Andric return false; 17406c3fb27SDimitry Andric case RISCV::SEXT_B: 17506c3fb27SDimitry Andric case RISCV::PACKH: 17606c3fb27SDimitry Andric if (Bits >= 8) 17706c3fb27SDimitry Andric break; 17806c3fb27SDimitry Andric return false; 17906c3fb27SDimitry Andric case RISCV::SEXT_H: 18006c3fb27SDimitry Andric case RISCV::FMV_H_X: 18106c3fb27SDimitry Andric case RISCV::ZEXT_H_RV32: 18206c3fb27SDimitry Andric case RISCV::ZEXT_H_RV64: 18306c3fb27SDimitry Andric case RISCV::PACKW: 18406c3fb27SDimitry Andric if (Bits >= 16) 18506c3fb27SDimitry Andric break; 18606c3fb27SDimitry Andric return false; 18706c3fb27SDimitry Andric 18806c3fb27SDimitry Andric case RISCV::PACK: 18906c3fb27SDimitry Andric if (Bits >= (ST.getXLen() / 2)) 19006c3fb27SDimitry Andric break; 19106c3fb27SDimitry Andric return false; 19206c3fb27SDimitry Andric 19306c3fb27SDimitry Andric case RISCV::SRLI: { 19406c3fb27SDimitry Andric // If we are shifting right by less than Bits, and users don't demand 19506c3fb27SDimitry Andric // any bits that were shifted into [Bits-1:0], then we can consider this 19606c3fb27SDimitry Andric // as an N-Bit user. 19706c3fb27SDimitry Andric unsigned ShAmt = UserMI->getOperand(2).getImm(); 19806c3fb27SDimitry Andric if (Bits > ShAmt) { 19906c3fb27SDimitry Andric Worklist.push_back(std::make_pair(UserMI, Bits - ShAmt)); 20006c3fb27SDimitry Andric break; 20106c3fb27SDimitry Andric } 20206c3fb27SDimitry Andric return false; 20306c3fb27SDimitry Andric } 20406c3fb27SDimitry Andric 20506c3fb27SDimitry Andric // these overwrite higher input bits, otherwise the lower word of output 20606c3fb27SDimitry Andric // depends only on the lower word of input. So check their uses read W. 20706c3fb27SDimitry Andric case RISCV::SLLI: 20806c3fb27SDimitry Andric if (Bits >= (ST.getXLen() - UserMI->getOperand(2).getImm())) 20906c3fb27SDimitry Andric break; 21006c3fb27SDimitry Andric Worklist.push_back(std::make_pair(UserMI, Bits)); 21106c3fb27SDimitry Andric break; 21206c3fb27SDimitry Andric case RISCV::ANDI: { 21306c3fb27SDimitry Andric uint64_t Imm = UserMI->getOperand(2).getImm(); 21406c3fb27SDimitry Andric if (Bits >= (unsigned)llvm::bit_width(Imm)) 21506c3fb27SDimitry Andric break; 21606c3fb27SDimitry Andric Worklist.push_back(std::make_pair(UserMI, Bits)); 21706c3fb27SDimitry Andric break; 21806c3fb27SDimitry Andric } 21906c3fb27SDimitry Andric case RISCV::ORI: { 22006c3fb27SDimitry Andric uint64_t Imm = UserMI->getOperand(2).getImm(); 22106c3fb27SDimitry Andric if (Bits >= (unsigned)llvm::bit_width<uint64_t>(~Imm)) 22206c3fb27SDimitry Andric break; 22306c3fb27SDimitry Andric Worklist.push_back(std::make_pair(UserMI, Bits)); 22406c3fb27SDimitry Andric break; 22506c3fb27SDimitry Andric } 22606c3fb27SDimitry Andric 22706c3fb27SDimitry Andric case RISCV::SLL: 22806c3fb27SDimitry Andric case RISCV::BSET: 22906c3fb27SDimitry Andric case RISCV::BCLR: 23006c3fb27SDimitry Andric case RISCV::BINV: 23106c3fb27SDimitry Andric // Operand 2 is the shift amount which uses log2(xlen) bits. 23206c3fb27SDimitry Andric if (OpIdx == 2) { 23306c3fb27SDimitry Andric if (Bits >= Log2_32(ST.getXLen())) 23406c3fb27SDimitry Andric break; 23506c3fb27SDimitry Andric return false; 23606c3fb27SDimitry Andric } 23706c3fb27SDimitry Andric Worklist.push_back(std::make_pair(UserMI, Bits)); 23806c3fb27SDimitry Andric break; 23906c3fb27SDimitry Andric 24006c3fb27SDimitry Andric case RISCV::SRA: 24106c3fb27SDimitry Andric case RISCV::SRL: 24206c3fb27SDimitry Andric case RISCV::ROL: 24306c3fb27SDimitry Andric case RISCV::ROR: 24406c3fb27SDimitry Andric // Operand 2 is the shift amount which uses 6 bits. 24506c3fb27SDimitry Andric if (OpIdx == 2 && Bits >= Log2_32(ST.getXLen())) 24606c3fb27SDimitry Andric break; 24706c3fb27SDimitry Andric return false; 24806c3fb27SDimitry Andric 24906c3fb27SDimitry Andric case RISCV::ADD_UW: 25006c3fb27SDimitry Andric case RISCV::SH1ADD_UW: 25106c3fb27SDimitry Andric case RISCV::SH2ADD_UW: 25206c3fb27SDimitry Andric case RISCV::SH3ADD_UW: 25306c3fb27SDimitry Andric // Operand 1 is implicitly zero extended. 25406c3fb27SDimitry Andric if (OpIdx == 1 && Bits >= 32) 25506c3fb27SDimitry Andric break; 25606c3fb27SDimitry Andric Worklist.push_back(std::make_pair(UserMI, Bits)); 25706c3fb27SDimitry Andric break; 25806c3fb27SDimitry Andric 25906c3fb27SDimitry Andric case RISCV::BEXTI: 26006c3fb27SDimitry Andric if (UserMI->getOperand(2).getImm() >= Bits) 26106c3fb27SDimitry Andric return false; 26206c3fb27SDimitry Andric break; 26306c3fb27SDimitry Andric 26406c3fb27SDimitry Andric case RISCV::SB: 26506c3fb27SDimitry Andric // The first argument is the value to store. 26606c3fb27SDimitry Andric if (OpIdx == 0 && Bits >= 8) 26706c3fb27SDimitry Andric break; 26806c3fb27SDimitry Andric return false; 26906c3fb27SDimitry Andric case RISCV::SH: 27006c3fb27SDimitry Andric // The first argument is the value to store. 27106c3fb27SDimitry Andric if (OpIdx == 0 && Bits >= 16) 27206c3fb27SDimitry Andric break; 27306c3fb27SDimitry Andric return false; 27406c3fb27SDimitry Andric case RISCV::SW: 27506c3fb27SDimitry Andric // The first argument is the value to store. 27606c3fb27SDimitry Andric if (OpIdx == 0 && Bits >= 32) 27706c3fb27SDimitry Andric break; 27806c3fb27SDimitry Andric return false; 27906c3fb27SDimitry Andric 28006c3fb27SDimitry Andric // For these, lower word of output in these operations, depends only on 28106c3fb27SDimitry Andric // the lower word of input. So, we check all uses only read lower word. 28206c3fb27SDimitry Andric case RISCV::COPY: 28306c3fb27SDimitry Andric case RISCV::PHI: 28406c3fb27SDimitry Andric 28506c3fb27SDimitry Andric case RISCV::ADD: 28606c3fb27SDimitry Andric case RISCV::ADDI: 28706c3fb27SDimitry Andric case RISCV::AND: 28806c3fb27SDimitry Andric case RISCV::MUL: 28906c3fb27SDimitry Andric case RISCV::OR: 29006c3fb27SDimitry Andric case RISCV::SUB: 29106c3fb27SDimitry Andric case RISCV::XOR: 29206c3fb27SDimitry Andric case RISCV::XORI: 29306c3fb27SDimitry Andric 29406c3fb27SDimitry Andric case RISCV::ANDN: 29506c3fb27SDimitry Andric case RISCV::BREV8: 29606c3fb27SDimitry Andric case RISCV::CLMUL: 29706c3fb27SDimitry Andric case RISCV::ORC_B: 29806c3fb27SDimitry Andric case RISCV::ORN: 29906c3fb27SDimitry Andric case RISCV::SH1ADD: 30006c3fb27SDimitry Andric case RISCV::SH2ADD: 30106c3fb27SDimitry Andric case RISCV::SH3ADD: 30206c3fb27SDimitry Andric case RISCV::XNOR: 30306c3fb27SDimitry Andric case RISCV::BSETI: 30406c3fb27SDimitry Andric case RISCV::BCLRI: 30506c3fb27SDimitry Andric case RISCV::BINVI: 30606c3fb27SDimitry Andric Worklist.push_back(std::make_pair(UserMI, Bits)); 30706c3fb27SDimitry Andric break; 30806c3fb27SDimitry Andric 30906c3fb27SDimitry Andric case RISCV::PseudoCCMOVGPR: 31006c3fb27SDimitry Andric // Either operand 4 or operand 5 is returned by this instruction. If 31106c3fb27SDimitry Andric // only the lower word of the result is used, then only the lower word 31206c3fb27SDimitry Andric // of operand 4 and 5 is used. 31306c3fb27SDimitry Andric if (OpIdx != 4 && OpIdx != 5) 31406c3fb27SDimitry Andric return false; 31506c3fb27SDimitry Andric Worklist.push_back(std::make_pair(UserMI, Bits)); 31606c3fb27SDimitry Andric break; 31706c3fb27SDimitry Andric 3185f757f3fSDimitry Andric case RISCV::CZERO_EQZ: 3195f757f3fSDimitry Andric case RISCV::CZERO_NEZ: 32006c3fb27SDimitry Andric case RISCV::VT_MASKC: 32106c3fb27SDimitry Andric case RISCV::VT_MASKCN: 32206c3fb27SDimitry Andric if (OpIdx != 1) 32306c3fb27SDimitry Andric return false; 32406c3fb27SDimitry Andric Worklist.push_back(std::make_pair(UserMI, Bits)); 32506c3fb27SDimitry Andric break; 32606c3fb27SDimitry Andric } 32706c3fb27SDimitry Andric } 32806c3fb27SDimitry Andric } 32906c3fb27SDimitry Andric 33006c3fb27SDimitry Andric return true; 33106c3fb27SDimitry Andric } 33206c3fb27SDimitry Andric 33306c3fb27SDimitry Andric static bool hasAllWUsers(const MachineInstr &OrigMI, const RISCVSubtarget &ST, 33406c3fb27SDimitry Andric const MachineRegisterInfo &MRI) { 33506c3fb27SDimitry Andric return hasAllNBitUsers(OrigMI, ST, MRI, 32); 33606c3fb27SDimitry Andric } 33706c3fb27SDimitry Andric 33806c3fb27SDimitry Andric // This function returns true if the machine instruction always outputs a value 33906c3fb27SDimitry Andric // where bits 63:32 match bit 31. 34006c3fb27SDimitry Andric static bool isSignExtendingOpW(const MachineInstr &MI, 34106c3fb27SDimitry Andric const MachineRegisterInfo &MRI) { 34206c3fb27SDimitry Andric uint64_t TSFlags = MI.getDesc().TSFlags; 34306c3fb27SDimitry Andric 34406c3fb27SDimitry Andric // Instructions that can be determined from opcode are marked in tablegen. 34506c3fb27SDimitry Andric if (TSFlags & RISCVII::IsSignExtendingOpWMask) 34606c3fb27SDimitry Andric return true; 34706c3fb27SDimitry Andric 34806c3fb27SDimitry Andric // Special cases that require checking operands. 34906c3fb27SDimitry Andric switch (MI.getOpcode()) { 35006c3fb27SDimitry Andric // shifting right sufficiently makes the value 32-bit sign-extended 35106c3fb27SDimitry Andric case RISCV::SRAI: 35206c3fb27SDimitry Andric return MI.getOperand(2).getImm() >= 32; 35306c3fb27SDimitry Andric case RISCV::SRLI: 35406c3fb27SDimitry Andric return MI.getOperand(2).getImm() > 32; 35506c3fb27SDimitry Andric // The LI pattern ADDI rd, X0, imm is sign extended. 35606c3fb27SDimitry Andric case RISCV::ADDI: 35706c3fb27SDimitry Andric return MI.getOperand(1).isReg() && MI.getOperand(1).getReg() == RISCV::X0; 35806c3fb27SDimitry Andric // An ANDI with an 11 bit immediate will zero bits 63:11. 35906c3fb27SDimitry Andric case RISCV::ANDI: 36006c3fb27SDimitry Andric return isUInt<11>(MI.getOperand(2).getImm()); 36106c3fb27SDimitry Andric // An ORI with an >11 bit immediate (negative 12-bit) will set bits 63:11. 36206c3fb27SDimitry Andric case RISCV::ORI: 36306c3fb27SDimitry Andric return !isUInt<11>(MI.getOperand(2).getImm()); 3645f757f3fSDimitry Andric // A bseti with X0 is sign extended if the immediate is less than 31. 3655f757f3fSDimitry Andric case RISCV::BSETI: 3665f757f3fSDimitry Andric return MI.getOperand(2).getImm() < 31 && 3675f757f3fSDimitry Andric MI.getOperand(1).getReg() == RISCV::X0; 36806c3fb27SDimitry Andric // Copying from X0 produces zero. 36906c3fb27SDimitry Andric case RISCV::COPY: 37006c3fb27SDimitry Andric return MI.getOperand(1).getReg() == RISCV::X0; 3715f757f3fSDimitry Andric case RISCV::PseudoAtomicLoadNand32: 3725f757f3fSDimitry Andric return true; 373*7a6dacacSDimitry Andric case RISCV::PseudoVMV_X_S: { 3745f757f3fSDimitry Andric // vmv.x.s has at least 33 sign bits if log2(sew) <= 5. 3755f757f3fSDimitry Andric int64_t Log2SEW = MI.getOperand(2).getImm(); 3765f757f3fSDimitry Andric assert(Log2SEW >= 3 && Log2SEW <= 6 && "Unexpected Log2SEW"); 3775f757f3fSDimitry Andric return Log2SEW <= 5; 3785f757f3fSDimitry Andric } 37906c3fb27SDimitry Andric } 38006c3fb27SDimitry Andric 38106c3fb27SDimitry Andric return false; 38206c3fb27SDimitry Andric } 38306c3fb27SDimitry Andric 38406c3fb27SDimitry Andric static bool isSignExtendedW(Register SrcReg, const RISCVSubtarget &ST, 38506c3fb27SDimitry Andric const MachineRegisterInfo &MRI, 38606c3fb27SDimitry Andric SmallPtrSetImpl<MachineInstr *> &FixableDef) { 38706c3fb27SDimitry Andric 38806c3fb27SDimitry Andric SmallPtrSet<const MachineInstr *, 4> Visited; 38906c3fb27SDimitry Andric SmallVector<MachineInstr *, 4> Worklist; 39006c3fb27SDimitry Andric 39106c3fb27SDimitry Andric auto AddRegDefToWorkList = [&](Register SrcReg) { 39206c3fb27SDimitry Andric if (!SrcReg.isVirtual()) 39306c3fb27SDimitry Andric return false; 39406c3fb27SDimitry Andric MachineInstr *SrcMI = MRI.getVRegDef(SrcReg); 39506c3fb27SDimitry Andric if (!SrcMI) 39606c3fb27SDimitry Andric return false; 3975f757f3fSDimitry Andric // Code assumes the register is operand 0. 3985f757f3fSDimitry Andric // TODO: Maybe the worklist should store register? 3995f757f3fSDimitry Andric if (!SrcMI->getOperand(0).isReg() || 4005f757f3fSDimitry Andric SrcMI->getOperand(0).getReg() != SrcReg) 4015f757f3fSDimitry Andric return false; 40206c3fb27SDimitry Andric // Add SrcMI to the worklist. 40306c3fb27SDimitry Andric Worklist.push_back(SrcMI); 40406c3fb27SDimitry Andric return true; 40506c3fb27SDimitry Andric }; 40606c3fb27SDimitry Andric 40706c3fb27SDimitry Andric if (!AddRegDefToWorkList(SrcReg)) 40806c3fb27SDimitry Andric return false; 40906c3fb27SDimitry Andric 41006c3fb27SDimitry Andric while (!Worklist.empty()) { 41106c3fb27SDimitry Andric MachineInstr *MI = Worklist.pop_back_val(); 41206c3fb27SDimitry Andric 41306c3fb27SDimitry Andric // If we already visited this instruction, we don't need to check it again. 41406c3fb27SDimitry Andric if (!Visited.insert(MI).second) 41506c3fb27SDimitry Andric continue; 41606c3fb27SDimitry Andric 41706c3fb27SDimitry Andric // If this is a sign extending operation we don't need to look any further. 41806c3fb27SDimitry Andric if (isSignExtendingOpW(*MI, MRI)) 41906c3fb27SDimitry Andric continue; 42006c3fb27SDimitry Andric 42106c3fb27SDimitry Andric // Is this an instruction that propagates sign extend? 42206c3fb27SDimitry Andric switch (MI->getOpcode()) { 42306c3fb27SDimitry Andric default: 42406c3fb27SDimitry Andric // Unknown opcode, give up. 42506c3fb27SDimitry Andric return false; 42606c3fb27SDimitry Andric case RISCV::COPY: { 42706c3fb27SDimitry Andric const MachineFunction *MF = MI->getMF(); 42806c3fb27SDimitry Andric const RISCVMachineFunctionInfo *RVFI = 42906c3fb27SDimitry Andric MF->getInfo<RISCVMachineFunctionInfo>(); 43006c3fb27SDimitry Andric 43106c3fb27SDimitry Andric // If this is the entry block and the register is livein, see if we know 43206c3fb27SDimitry Andric // it is sign extended. 43306c3fb27SDimitry Andric if (MI->getParent() == &MF->front()) { 43406c3fb27SDimitry Andric Register VReg = MI->getOperand(0).getReg(); 43506c3fb27SDimitry Andric if (MF->getRegInfo().isLiveIn(VReg) && RVFI->isSExt32Register(VReg)) 43606c3fb27SDimitry Andric continue; 43706c3fb27SDimitry Andric } 43806c3fb27SDimitry Andric 43906c3fb27SDimitry Andric Register CopySrcReg = MI->getOperand(1).getReg(); 44006c3fb27SDimitry Andric if (CopySrcReg == RISCV::X10) { 44106c3fb27SDimitry Andric // For a method return value, we check the ZExt/SExt flags in attribute. 44206c3fb27SDimitry Andric // We assume the following code sequence for method call. 44306c3fb27SDimitry Andric // PseudoCALL @bar, ... 44406c3fb27SDimitry Andric // ADJCALLSTACKUP 0, 0, implicit-def dead $x2, implicit $x2 44506c3fb27SDimitry Andric // %0:gpr = COPY $x10 44606c3fb27SDimitry Andric // 44706c3fb27SDimitry Andric // We use the PseudoCall to look up the IR function being called to find 44806c3fb27SDimitry Andric // its return attributes. 44906c3fb27SDimitry Andric const MachineBasicBlock *MBB = MI->getParent(); 45006c3fb27SDimitry Andric auto II = MI->getIterator(); 45106c3fb27SDimitry Andric if (II == MBB->instr_begin() || 45206c3fb27SDimitry Andric (--II)->getOpcode() != RISCV::ADJCALLSTACKUP) 45306c3fb27SDimitry Andric return false; 45406c3fb27SDimitry Andric 45506c3fb27SDimitry Andric const MachineInstr &CallMI = *(--II); 45606c3fb27SDimitry Andric if (!CallMI.isCall() || !CallMI.getOperand(0).isGlobal()) 45706c3fb27SDimitry Andric return false; 45806c3fb27SDimitry Andric 45906c3fb27SDimitry Andric auto *CalleeFn = 46006c3fb27SDimitry Andric dyn_cast_if_present<Function>(CallMI.getOperand(0).getGlobal()); 46106c3fb27SDimitry Andric if (!CalleeFn) 46206c3fb27SDimitry Andric return false; 46306c3fb27SDimitry Andric 46406c3fb27SDimitry Andric auto *IntTy = dyn_cast<IntegerType>(CalleeFn->getReturnType()); 46506c3fb27SDimitry Andric if (!IntTy) 46606c3fb27SDimitry Andric return false; 46706c3fb27SDimitry Andric 46806c3fb27SDimitry Andric const AttributeSet &Attrs = CalleeFn->getAttributes().getRetAttrs(); 46906c3fb27SDimitry Andric unsigned BitWidth = IntTy->getBitWidth(); 47006c3fb27SDimitry Andric if ((BitWidth <= 32 && Attrs.hasAttribute(Attribute::SExt)) || 47106c3fb27SDimitry Andric (BitWidth < 32 && Attrs.hasAttribute(Attribute::ZExt))) 47206c3fb27SDimitry Andric continue; 47306c3fb27SDimitry Andric } 47406c3fb27SDimitry Andric 47506c3fb27SDimitry Andric if (!AddRegDefToWorkList(CopySrcReg)) 47606c3fb27SDimitry Andric return false; 47706c3fb27SDimitry Andric 47806c3fb27SDimitry Andric break; 47906c3fb27SDimitry Andric } 48006c3fb27SDimitry Andric 48106c3fb27SDimitry Andric // For these, we just need to check if the 1st operand is sign extended. 48206c3fb27SDimitry Andric case RISCV::BCLRI: 48306c3fb27SDimitry Andric case RISCV::BINVI: 48406c3fb27SDimitry Andric case RISCV::BSETI: 48506c3fb27SDimitry Andric if (MI->getOperand(2).getImm() >= 31) 48606c3fb27SDimitry Andric return false; 48706c3fb27SDimitry Andric [[fallthrough]]; 48806c3fb27SDimitry Andric case RISCV::REM: 48906c3fb27SDimitry Andric case RISCV::ANDI: 49006c3fb27SDimitry Andric case RISCV::ORI: 49106c3fb27SDimitry Andric case RISCV::XORI: 49206c3fb27SDimitry Andric // |Remainder| is always <= |Dividend|. If D is 32-bit, then so is R. 49306c3fb27SDimitry Andric // DIV doesn't work because of the edge case 0xf..f 8000 0000 / (long)-1 49406c3fb27SDimitry Andric // Logical operations use a sign extended 12-bit immediate. 49506c3fb27SDimitry Andric if (!AddRegDefToWorkList(MI->getOperand(1).getReg())) 49606c3fb27SDimitry Andric return false; 49706c3fb27SDimitry Andric 49806c3fb27SDimitry Andric break; 49906c3fb27SDimitry Andric case RISCV::PseudoCCADDW: 5005f757f3fSDimitry Andric case RISCV::PseudoCCADDIW: 50106c3fb27SDimitry Andric case RISCV::PseudoCCSUBW: 5025f757f3fSDimitry Andric case RISCV::PseudoCCSLLW: 5035f757f3fSDimitry Andric case RISCV::PseudoCCSRLW: 5045f757f3fSDimitry Andric case RISCV::PseudoCCSRAW: 5055f757f3fSDimitry Andric case RISCV::PseudoCCSLLIW: 5065f757f3fSDimitry Andric case RISCV::PseudoCCSRLIW: 5075f757f3fSDimitry Andric case RISCV::PseudoCCSRAIW: 5085f757f3fSDimitry Andric // Returns operand 4 or an ADDW/SUBW/etc. of operands 5 and 6. We only 5095f757f3fSDimitry Andric // need to check if operand 4 is sign extended. 51006c3fb27SDimitry Andric if (!AddRegDefToWorkList(MI->getOperand(4).getReg())) 51106c3fb27SDimitry Andric return false; 51206c3fb27SDimitry Andric break; 51306c3fb27SDimitry Andric case RISCV::REMU: 51406c3fb27SDimitry Andric case RISCV::AND: 51506c3fb27SDimitry Andric case RISCV::OR: 51606c3fb27SDimitry Andric case RISCV::XOR: 51706c3fb27SDimitry Andric case RISCV::ANDN: 51806c3fb27SDimitry Andric case RISCV::ORN: 51906c3fb27SDimitry Andric case RISCV::XNOR: 52006c3fb27SDimitry Andric case RISCV::MAX: 52106c3fb27SDimitry Andric case RISCV::MAXU: 52206c3fb27SDimitry Andric case RISCV::MIN: 52306c3fb27SDimitry Andric case RISCV::MINU: 52406c3fb27SDimitry Andric case RISCV::PseudoCCMOVGPR: 52506c3fb27SDimitry Andric case RISCV::PseudoCCAND: 52606c3fb27SDimitry Andric case RISCV::PseudoCCOR: 52706c3fb27SDimitry Andric case RISCV::PseudoCCXOR: 52806c3fb27SDimitry Andric case RISCV::PHI: { 52906c3fb27SDimitry Andric // If all incoming values are sign-extended, the output of AND, OR, XOR, 53006c3fb27SDimitry Andric // MIN, MAX, or PHI is also sign-extended. 53106c3fb27SDimitry Andric 53206c3fb27SDimitry Andric // The input registers for PHI are operand 1, 3, ... 53306c3fb27SDimitry Andric // The input registers for PseudoCCMOVGPR are 4 and 5. 53406c3fb27SDimitry Andric // The input registers for PseudoCCAND/OR/XOR are 4, 5, and 6. 53506c3fb27SDimitry Andric // The input registers for others are operand 1 and 2. 53606c3fb27SDimitry Andric unsigned B = 1, E = 3, D = 1; 53706c3fb27SDimitry Andric switch (MI->getOpcode()) { 53806c3fb27SDimitry Andric case RISCV::PHI: 53906c3fb27SDimitry Andric E = MI->getNumOperands(); 54006c3fb27SDimitry Andric D = 2; 54106c3fb27SDimitry Andric break; 54206c3fb27SDimitry Andric case RISCV::PseudoCCMOVGPR: 54306c3fb27SDimitry Andric B = 4; 54406c3fb27SDimitry Andric E = 6; 54506c3fb27SDimitry Andric break; 54606c3fb27SDimitry Andric case RISCV::PseudoCCAND: 54706c3fb27SDimitry Andric case RISCV::PseudoCCOR: 54806c3fb27SDimitry Andric case RISCV::PseudoCCXOR: 54906c3fb27SDimitry Andric B = 4; 55006c3fb27SDimitry Andric E = 7; 55106c3fb27SDimitry Andric break; 55206c3fb27SDimitry Andric } 55306c3fb27SDimitry Andric 55406c3fb27SDimitry Andric for (unsigned I = B; I != E; I += D) { 55506c3fb27SDimitry Andric if (!MI->getOperand(I).isReg()) 55606c3fb27SDimitry Andric return false; 55706c3fb27SDimitry Andric 55806c3fb27SDimitry Andric if (!AddRegDefToWorkList(MI->getOperand(I).getReg())) 55906c3fb27SDimitry Andric return false; 56006c3fb27SDimitry Andric } 56106c3fb27SDimitry Andric 56206c3fb27SDimitry Andric break; 56306c3fb27SDimitry Andric } 56406c3fb27SDimitry Andric 5655f757f3fSDimitry Andric case RISCV::CZERO_EQZ: 5665f757f3fSDimitry Andric case RISCV::CZERO_NEZ: 56706c3fb27SDimitry Andric case RISCV::VT_MASKC: 56806c3fb27SDimitry Andric case RISCV::VT_MASKCN: 56906c3fb27SDimitry Andric // Instructions return zero or operand 1. Result is sign extended if 57006c3fb27SDimitry Andric // operand 1 is sign extended. 57106c3fb27SDimitry Andric if (!AddRegDefToWorkList(MI->getOperand(1).getReg())) 57206c3fb27SDimitry Andric return false; 57306c3fb27SDimitry Andric break; 57406c3fb27SDimitry Andric 57506c3fb27SDimitry Andric // With these opcode, we can "fix" them with the W-version 57606c3fb27SDimitry Andric // if we know all users of the result only rely on bits 31:0 57706c3fb27SDimitry Andric case RISCV::SLLI: 57806c3fb27SDimitry Andric // SLLIW reads the lowest 5 bits, while SLLI reads lowest 6 bits 57906c3fb27SDimitry Andric if (MI->getOperand(2).getImm() >= 32) 58006c3fb27SDimitry Andric return false; 58106c3fb27SDimitry Andric [[fallthrough]]; 58206c3fb27SDimitry Andric case RISCV::ADDI: 58306c3fb27SDimitry Andric case RISCV::ADD: 58406c3fb27SDimitry Andric case RISCV::LD: 58506c3fb27SDimitry Andric case RISCV::LWU: 58606c3fb27SDimitry Andric case RISCV::MUL: 58706c3fb27SDimitry Andric case RISCV::SUB: 58806c3fb27SDimitry Andric if (hasAllWUsers(*MI, ST, MRI)) { 58906c3fb27SDimitry Andric FixableDef.insert(MI); 59006c3fb27SDimitry Andric break; 59106c3fb27SDimitry Andric } 59206c3fb27SDimitry Andric return false; 59306c3fb27SDimitry Andric } 59406c3fb27SDimitry Andric } 59506c3fb27SDimitry Andric 59606c3fb27SDimitry Andric // If we get here, then every node we visited produces a sign extended value 59706c3fb27SDimitry Andric // or propagated sign extended values. So the result must be sign extended. 59806c3fb27SDimitry Andric return true; 59906c3fb27SDimitry Andric } 60006c3fb27SDimitry Andric 60106c3fb27SDimitry Andric static unsigned getWOp(unsigned Opcode) { 60206c3fb27SDimitry Andric switch (Opcode) { 60306c3fb27SDimitry Andric case RISCV::ADDI: 60406c3fb27SDimitry Andric return RISCV::ADDIW; 60506c3fb27SDimitry Andric case RISCV::ADD: 60606c3fb27SDimitry Andric return RISCV::ADDW; 60706c3fb27SDimitry Andric case RISCV::LD: 60806c3fb27SDimitry Andric case RISCV::LWU: 60906c3fb27SDimitry Andric return RISCV::LW; 61006c3fb27SDimitry Andric case RISCV::MUL: 61106c3fb27SDimitry Andric return RISCV::MULW; 61206c3fb27SDimitry Andric case RISCV::SLLI: 61306c3fb27SDimitry Andric return RISCV::SLLIW; 61406c3fb27SDimitry Andric case RISCV::SUB: 61506c3fb27SDimitry Andric return RISCV::SUBW; 61606c3fb27SDimitry Andric default: 61706c3fb27SDimitry Andric llvm_unreachable("Unexpected opcode for replacement with W variant"); 61806c3fb27SDimitry Andric } 61906c3fb27SDimitry Andric } 62006c3fb27SDimitry Andric 62106c3fb27SDimitry Andric bool RISCVOptWInstrs::removeSExtWInstrs(MachineFunction &MF, 62206c3fb27SDimitry Andric const RISCVInstrInfo &TII, 62306c3fb27SDimitry Andric const RISCVSubtarget &ST, 62406c3fb27SDimitry Andric MachineRegisterInfo &MRI) { 62506c3fb27SDimitry Andric if (DisableSExtWRemoval) 62606c3fb27SDimitry Andric return false; 62706c3fb27SDimitry Andric 62806c3fb27SDimitry Andric bool MadeChange = false; 62906c3fb27SDimitry Andric for (MachineBasicBlock &MBB : MF) { 6305f757f3fSDimitry Andric for (MachineInstr &MI : llvm::make_early_inc_range(MBB)) { 63106c3fb27SDimitry Andric // We're looking for the sext.w pattern ADDIW rd, rs1, 0. 6325f757f3fSDimitry Andric if (!RISCV::isSEXT_W(MI)) 63306c3fb27SDimitry Andric continue; 63406c3fb27SDimitry Andric 6355f757f3fSDimitry Andric Register SrcReg = MI.getOperand(1).getReg(); 63606c3fb27SDimitry Andric 63706c3fb27SDimitry Andric SmallPtrSet<MachineInstr *, 4> FixableDefs; 63806c3fb27SDimitry Andric 63906c3fb27SDimitry Andric // If all users only use the lower bits, this sext.w is redundant. 64006c3fb27SDimitry Andric // Or if all definitions reaching MI sign-extend their output, 64106c3fb27SDimitry Andric // then sext.w is redundant. 6425f757f3fSDimitry Andric if (!hasAllWUsers(MI, ST, MRI) && 64306c3fb27SDimitry Andric !isSignExtendedW(SrcReg, ST, MRI, FixableDefs)) 64406c3fb27SDimitry Andric continue; 64506c3fb27SDimitry Andric 6465f757f3fSDimitry Andric Register DstReg = MI.getOperand(0).getReg(); 64706c3fb27SDimitry Andric if (!MRI.constrainRegClass(SrcReg, MRI.getRegClass(DstReg))) 64806c3fb27SDimitry Andric continue; 64906c3fb27SDimitry Andric 65006c3fb27SDimitry Andric // Convert Fixable instructions to their W versions. 65106c3fb27SDimitry Andric for (MachineInstr *Fixable : FixableDefs) { 65206c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << "Replacing " << *Fixable); 65306c3fb27SDimitry Andric Fixable->setDesc(TII.get(getWOp(Fixable->getOpcode()))); 65406c3fb27SDimitry Andric Fixable->clearFlag(MachineInstr::MIFlag::NoSWrap); 65506c3fb27SDimitry Andric Fixable->clearFlag(MachineInstr::MIFlag::NoUWrap); 65606c3fb27SDimitry Andric Fixable->clearFlag(MachineInstr::MIFlag::IsExact); 65706c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << " with " << *Fixable); 65806c3fb27SDimitry Andric ++NumTransformedToWInstrs; 65906c3fb27SDimitry Andric } 66006c3fb27SDimitry Andric 66106c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << "Removing redundant sign-extension\n"); 66206c3fb27SDimitry Andric MRI.replaceRegWith(DstReg, SrcReg); 66306c3fb27SDimitry Andric MRI.clearKillFlags(SrcReg); 6645f757f3fSDimitry Andric MI.eraseFromParent(); 66506c3fb27SDimitry Andric ++NumRemovedSExtW; 66606c3fb27SDimitry Andric MadeChange = true; 66706c3fb27SDimitry Andric } 66806c3fb27SDimitry Andric } 66906c3fb27SDimitry Andric 67006c3fb27SDimitry Andric return MadeChange; 67106c3fb27SDimitry Andric } 67206c3fb27SDimitry Andric 67306c3fb27SDimitry Andric bool RISCVOptWInstrs::stripWSuffixes(MachineFunction &MF, 67406c3fb27SDimitry Andric const RISCVInstrInfo &TII, 67506c3fb27SDimitry Andric const RISCVSubtarget &ST, 67606c3fb27SDimitry Andric MachineRegisterInfo &MRI) { 67706c3fb27SDimitry Andric if (DisableStripWSuffix) 67806c3fb27SDimitry Andric return false; 67906c3fb27SDimitry Andric 68006c3fb27SDimitry Andric bool MadeChange = false; 68106c3fb27SDimitry Andric for (MachineBasicBlock &MBB : MF) { 6825f757f3fSDimitry Andric for (MachineInstr &MI : MBB) { 68306c3fb27SDimitry Andric unsigned Opc; 68406c3fb27SDimitry Andric switch (MI.getOpcode()) { 68506c3fb27SDimitry Andric default: 68606c3fb27SDimitry Andric continue; 68706c3fb27SDimitry Andric case RISCV::ADDW: Opc = RISCV::ADD; break; 6885f757f3fSDimitry Andric case RISCV::ADDIW: Opc = RISCV::ADDI; break; 68906c3fb27SDimitry Andric case RISCV::MULW: Opc = RISCV::MUL; break; 69006c3fb27SDimitry Andric case RISCV::SLLIW: Opc = RISCV::SLLI; break; 69106c3fb27SDimitry Andric } 69206c3fb27SDimitry Andric 69306c3fb27SDimitry Andric if (hasAllWUsers(MI, ST, MRI)) { 69406c3fb27SDimitry Andric MI.setDesc(TII.get(Opc)); 69506c3fb27SDimitry Andric MadeChange = true; 69606c3fb27SDimitry Andric } 69706c3fb27SDimitry Andric } 69806c3fb27SDimitry Andric } 69906c3fb27SDimitry Andric 70006c3fb27SDimitry Andric return MadeChange; 70106c3fb27SDimitry Andric } 70206c3fb27SDimitry Andric 70306c3fb27SDimitry Andric bool RISCVOptWInstrs::runOnMachineFunction(MachineFunction &MF) { 70406c3fb27SDimitry Andric if (skipFunction(MF.getFunction())) 70506c3fb27SDimitry Andric return false; 70606c3fb27SDimitry Andric 70706c3fb27SDimitry Andric MachineRegisterInfo &MRI = MF.getRegInfo(); 70806c3fb27SDimitry Andric const RISCVSubtarget &ST = MF.getSubtarget<RISCVSubtarget>(); 70906c3fb27SDimitry Andric const RISCVInstrInfo &TII = *ST.getInstrInfo(); 71006c3fb27SDimitry Andric 71106c3fb27SDimitry Andric if (!ST.is64Bit()) 71206c3fb27SDimitry Andric return false; 71306c3fb27SDimitry Andric 71406c3fb27SDimitry Andric bool MadeChange = false; 71506c3fb27SDimitry Andric MadeChange |= removeSExtWInstrs(MF, TII, ST, MRI); 71606c3fb27SDimitry Andric MadeChange |= stripWSuffixes(MF, TII, ST, MRI); 71706c3fb27SDimitry Andric 71806c3fb27SDimitry Andric return MadeChange; 71906c3fb27SDimitry Andric } 720