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 // 15*5f757f3fSDimitry Andric // Then it removes the -w suffix from opw instructions whenever all users are 16*5f757f3fSDimitry Andric // dependent only on the lower word of the result of the instruction. 17*5f757f3fSDimitry Andric // The cases handled are: 18*5f757f3fSDimitry Andric // * addw because c.add has a larger register encoding than c.addw. 19*5f757f3fSDimitry Andric // * addiw because it helps reduce test differences between RV32 and RV64 20*5f757f3fSDimitry Andric // w/o being a pessimization. 21*5f757f3fSDimitry Andric // * mulw because c.mulw doesn't exist but c.mul does (w/ zcb) 22*5f757f3fSDimitry 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" 29*5f757f3fSDimitry 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 56*5f757f3fSDimitry 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 82*5f757f3fSDimitry Andric static bool vectorPseudoHasAllNBitUsers(const MachineOperand &UserOp, 83*5f757f3fSDimitry Andric unsigned Bits) { 84*5f757f3fSDimitry Andric const MachineInstr &MI = *UserOp.getParent(); 85*5f757f3fSDimitry Andric unsigned MCOpcode = RISCV::getRVVMCOpcode(MI.getOpcode()); 86*5f757f3fSDimitry Andric 87*5f757f3fSDimitry Andric if (!MCOpcode) 88*5f757f3fSDimitry Andric return false; 89*5f757f3fSDimitry Andric 90*5f757f3fSDimitry Andric const MCInstrDesc &MCID = MI.getDesc(); 91*5f757f3fSDimitry Andric const uint64_t TSFlags = MCID.TSFlags; 92*5f757f3fSDimitry Andric if (!RISCVII::hasSEWOp(TSFlags)) 93*5f757f3fSDimitry Andric return false; 94*5f757f3fSDimitry Andric assert(RISCVII::hasVLOp(TSFlags)); 95*5f757f3fSDimitry Andric const unsigned Log2SEW = MI.getOperand(RISCVII::getSEWOpNum(MCID)).getImm(); 96*5f757f3fSDimitry Andric 97*5f757f3fSDimitry Andric if (UserOp.getOperandNo() == RISCVII::getVLOpNum(MCID)) 98*5f757f3fSDimitry Andric return false; 99*5f757f3fSDimitry Andric 100*5f757f3fSDimitry Andric auto NumDemandedBits = 101*5f757f3fSDimitry Andric RISCV::getVectorLowDemandedScalarBits(MCOpcode, Log2SEW); 102*5f757f3fSDimitry Andric return NumDemandedBits && Bits >= *NumDemandedBits; 103*5f757f3fSDimitry Andric } 104*5f757f3fSDimitry 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 129*5f757f3fSDimitry Andric for (auto &UserOp : MRI.use_nodbg_operands(MI->getOperand(0).getReg())) { 13006c3fb27SDimitry Andric const MachineInstr *UserMI = UserOp.getParent(); 13106c3fb27SDimitry Andric unsigned OpIdx = UserOp.getOperandNo(); 13206c3fb27SDimitry Andric 13306c3fb27SDimitry Andric switch (UserMI->getOpcode()) { 13406c3fb27SDimitry Andric default: 135*5f757f3fSDimitry Andric if (vectorPseudoHasAllNBitUsers(UserOp, Bits)) 136*5f757f3fSDimitry Andric break; 13706c3fb27SDimitry Andric return false; 13806c3fb27SDimitry Andric 13906c3fb27SDimitry Andric case RISCV::ADDIW: 14006c3fb27SDimitry Andric case RISCV::ADDW: 14106c3fb27SDimitry Andric case RISCV::DIVUW: 14206c3fb27SDimitry Andric case RISCV::DIVW: 14306c3fb27SDimitry Andric case RISCV::MULW: 14406c3fb27SDimitry Andric case RISCV::REMUW: 14506c3fb27SDimitry Andric case RISCV::REMW: 14606c3fb27SDimitry Andric case RISCV::SLLIW: 14706c3fb27SDimitry Andric case RISCV::SLLW: 14806c3fb27SDimitry Andric case RISCV::SRAIW: 14906c3fb27SDimitry Andric case RISCV::SRAW: 15006c3fb27SDimitry Andric case RISCV::SRLIW: 15106c3fb27SDimitry Andric case RISCV::SRLW: 15206c3fb27SDimitry Andric case RISCV::SUBW: 15306c3fb27SDimitry Andric case RISCV::ROLW: 15406c3fb27SDimitry Andric case RISCV::RORW: 15506c3fb27SDimitry Andric case RISCV::RORIW: 15606c3fb27SDimitry Andric case RISCV::CLZW: 15706c3fb27SDimitry Andric case RISCV::CTZW: 15806c3fb27SDimitry Andric case RISCV::CPOPW: 15906c3fb27SDimitry Andric case RISCV::SLLI_UW: 16006c3fb27SDimitry Andric case RISCV::FMV_W_X: 16106c3fb27SDimitry Andric case RISCV::FCVT_H_W: 16206c3fb27SDimitry Andric case RISCV::FCVT_H_WU: 16306c3fb27SDimitry Andric case RISCV::FCVT_S_W: 16406c3fb27SDimitry Andric case RISCV::FCVT_S_WU: 16506c3fb27SDimitry Andric case RISCV::FCVT_D_W: 16606c3fb27SDimitry Andric case RISCV::FCVT_D_WU: 16706c3fb27SDimitry Andric if (Bits >= 32) 16806c3fb27SDimitry Andric break; 16906c3fb27SDimitry Andric return false; 17006c3fb27SDimitry Andric case RISCV::SEXT_B: 17106c3fb27SDimitry Andric case RISCV::PACKH: 17206c3fb27SDimitry Andric if (Bits >= 8) 17306c3fb27SDimitry Andric break; 17406c3fb27SDimitry Andric return false; 17506c3fb27SDimitry Andric case RISCV::SEXT_H: 17606c3fb27SDimitry Andric case RISCV::FMV_H_X: 17706c3fb27SDimitry Andric case RISCV::ZEXT_H_RV32: 17806c3fb27SDimitry Andric case RISCV::ZEXT_H_RV64: 17906c3fb27SDimitry Andric case RISCV::PACKW: 18006c3fb27SDimitry Andric if (Bits >= 16) 18106c3fb27SDimitry Andric break; 18206c3fb27SDimitry Andric return false; 18306c3fb27SDimitry Andric 18406c3fb27SDimitry Andric case RISCV::PACK: 18506c3fb27SDimitry Andric if (Bits >= (ST.getXLen() / 2)) 18606c3fb27SDimitry Andric break; 18706c3fb27SDimitry Andric return false; 18806c3fb27SDimitry Andric 18906c3fb27SDimitry Andric case RISCV::SRLI: { 19006c3fb27SDimitry Andric // If we are shifting right by less than Bits, and users don't demand 19106c3fb27SDimitry Andric // any bits that were shifted into [Bits-1:0], then we can consider this 19206c3fb27SDimitry Andric // as an N-Bit user. 19306c3fb27SDimitry Andric unsigned ShAmt = UserMI->getOperand(2).getImm(); 19406c3fb27SDimitry Andric if (Bits > ShAmt) { 19506c3fb27SDimitry Andric Worklist.push_back(std::make_pair(UserMI, Bits - ShAmt)); 19606c3fb27SDimitry Andric break; 19706c3fb27SDimitry Andric } 19806c3fb27SDimitry Andric return false; 19906c3fb27SDimitry Andric } 20006c3fb27SDimitry Andric 20106c3fb27SDimitry Andric // these overwrite higher input bits, otherwise the lower word of output 20206c3fb27SDimitry Andric // depends only on the lower word of input. So check their uses read W. 20306c3fb27SDimitry Andric case RISCV::SLLI: 20406c3fb27SDimitry Andric if (Bits >= (ST.getXLen() - UserMI->getOperand(2).getImm())) 20506c3fb27SDimitry Andric break; 20606c3fb27SDimitry Andric Worklist.push_back(std::make_pair(UserMI, Bits)); 20706c3fb27SDimitry Andric break; 20806c3fb27SDimitry Andric case RISCV::ANDI: { 20906c3fb27SDimitry Andric uint64_t Imm = UserMI->getOperand(2).getImm(); 21006c3fb27SDimitry Andric if (Bits >= (unsigned)llvm::bit_width(Imm)) 21106c3fb27SDimitry Andric break; 21206c3fb27SDimitry Andric Worklist.push_back(std::make_pair(UserMI, Bits)); 21306c3fb27SDimitry Andric break; 21406c3fb27SDimitry Andric } 21506c3fb27SDimitry Andric case RISCV::ORI: { 21606c3fb27SDimitry Andric uint64_t Imm = UserMI->getOperand(2).getImm(); 21706c3fb27SDimitry Andric if (Bits >= (unsigned)llvm::bit_width<uint64_t>(~Imm)) 21806c3fb27SDimitry Andric break; 21906c3fb27SDimitry Andric Worklist.push_back(std::make_pair(UserMI, Bits)); 22006c3fb27SDimitry Andric break; 22106c3fb27SDimitry Andric } 22206c3fb27SDimitry Andric 22306c3fb27SDimitry Andric case RISCV::SLL: 22406c3fb27SDimitry Andric case RISCV::BSET: 22506c3fb27SDimitry Andric case RISCV::BCLR: 22606c3fb27SDimitry Andric case RISCV::BINV: 22706c3fb27SDimitry Andric // Operand 2 is the shift amount which uses log2(xlen) bits. 22806c3fb27SDimitry Andric if (OpIdx == 2) { 22906c3fb27SDimitry Andric if (Bits >= Log2_32(ST.getXLen())) 23006c3fb27SDimitry Andric break; 23106c3fb27SDimitry Andric return false; 23206c3fb27SDimitry Andric } 23306c3fb27SDimitry Andric Worklist.push_back(std::make_pair(UserMI, Bits)); 23406c3fb27SDimitry Andric break; 23506c3fb27SDimitry Andric 23606c3fb27SDimitry Andric case RISCV::SRA: 23706c3fb27SDimitry Andric case RISCV::SRL: 23806c3fb27SDimitry Andric case RISCV::ROL: 23906c3fb27SDimitry Andric case RISCV::ROR: 24006c3fb27SDimitry Andric // Operand 2 is the shift amount which uses 6 bits. 24106c3fb27SDimitry Andric if (OpIdx == 2 && Bits >= Log2_32(ST.getXLen())) 24206c3fb27SDimitry Andric break; 24306c3fb27SDimitry Andric return false; 24406c3fb27SDimitry Andric 24506c3fb27SDimitry Andric case RISCV::ADD_UW: 24606c3fb27SDimitry Andric case RISCV::SH1ADD_UW: 24706c3fb27SDimitry Andric case RISCV::SH2ADD_UW: 24806c3fb27SDimitry Andric case RISCV::SH3ADD_UW: 24906c3fb27SDimitry Andric // Operand 1 is implicitly zero extended. 25006c3fb27SDimitry Andric if (OpIdx == 1 && Bits >= 32) 25106c3fb27SDimitry Andric break; 25206c3fb27SDimitry Andric Worklist.push_back(std::make_pair(UserMI, Bits)); 25306c3fb27SDimitry Andric break; 25406c3fb27SDimitry Andric 25506c3fb27SDimitry Andric case RISCV::BEXTI: 25606c3fb27SDimitry Andric if (UserMI->getOperand(2).getImm() >= Bits) 25706c3fb27SDimitry Andric return false; 25806c3fb27SDimitry Andric break; 25906c3fb27SDimitry Andric 26006c3fb27SDimitry Andric case RISCV::SB: 26106c3fb27SDimitry Andric // The first argument is the value to store. 26206c3fb27SDimitry Andric if (OpIdx == 0 && Bits >= 8) 26306c3fb27SDimitry Andric break; 26406c3fb27SDimitry Andric return false; 26506c3fb27SDimitry Andric case RISCV::SH: 26606c3fb27SDimitry Andric // The first argument is the value to store. 26706c3fb27SDimitry Andric if (OpIdx == 0 && Bits >= 16) 26806c3fb27SDimitry Andric break; 26906c3fb27SDimitry Andric return false; 27006c3fb27SDimitry Andric case RISCV::SW: 27106c3fb27SDimitry Andric // The first argument is the value to store. 27206c3fb27SDimitry Andric if (OpIdx == 0 && Bits >= 32) 27306c3fb27SDimitry Andric break; 27406c3fb27SDimitry Andric return false; 27506c3fb27SDimitry Andric 27606c3fb27SDimitry Andric // For these, lower word of output in these operations, depends only on 27706c3fb27SDimitry Andric // the lower word of input. So, we check all uses only read lower word. 27806c3fb27SDimitry Andric case RISCV::COPY: 27906c3fb27SDimitry Andric case RISCV::PHI: 28006c3fb27SDimitry Andric 28106c3fb27SDimitry Andric case RISCV::ADD: 28206c3fb27SDimitry Andric case RISCV::ADDI: 28306c3fb27SDimitry Andric case RISCV::AND: 28406c3fb27SDimitry Andric case RISCV::MUL: 28506c3fb27SDimitry Andric case RISCV::OR: 28606c3fb27SDimitry Andric case RISCV::SUB: 28706c3fb27SDimitry Andric case RISCV::XOR: 28806c3fb27SDimitry Andric case RISCV::XORI: 28906c3fb27SDimitry Andric 29006c3fb27SDimitry Andric case RISCV::ANDN: 29106c3fb27SDimitry Andric case RISCV::BREV8: 29206c3fb27SDimitry Andric case RISCV::CLMUL: 29306c3fb27SDimitry Andric case RISCV::ORC_B: 29406c3fb27SDimitry Andric case RISCV::ORN: 29506c3fb27SDimitry Andric case RISCV::SH1ADD: 29606c3fb27SDimitry Andric case RISCV::SH2ADD: 29706c3fb27SDimitry Andric case RISCV::SH3ADD: 29806c3fb27SDimitry Andric case RISCV::XNOR: 29906c3fb27SDimitry Andric case RISCV::BSETI: 30006c3fb27SDimitry Andric case RISCV::BCLRI: 30106c3fb27SDimitry Andric case RISCV::BINVI: 30206c3fb27SDimitry Andric Worklist.push_back(std::make_pair(UserMI, Bits)); 30306c3fb27SDimitry Andric break; 30406c3fb27SDimitry Andric 30506c3fb27SDimitry Andric case RISCV::PseudoCCMOVGPR: 30606c3fb27SDimitry Andric // Either operand 4 or operand 5 is returned by this instruction. If 30706c3fb27SDimitry Andric // only the lower word of the result is used, then only the lower word 30806c3fb27SDimitry Andric // of operand 4 and 5 is used. 30906c3fb27SDimitry Andric if (OpIdx != 4 && OpIdx != 5) 31006c3fb27SDimitry Andric return false; 31106c3fb27SDimitry Andric Worklist.push_back(std::make_pair(UserMI, Bits)); 31206c3fb27SDimitry Andric break; 31306c3fb27SDimitry Andric 314*5f757f3fSDimitry Andric case RISCV::CZERO_EQZ: 315*5f757f3fSDimitry Andric case RISCV::CZERO_NEZ: 31606c3fb27SDimitry Andric case RISCV::VT_MASKC: 31706c3fb27SDimitry Andric case RISCV::VT_MASKCN: 31806c3fb27SDimitry Andric if (OpIdx != 1) 31906c3fb27SDimitry Andric return false; 32006c3fb27SDimitry Andric Worklist.push_back(std::make_pair(UserMI, Bits)); 32106c3fb27SDimitry Andric break; 32206c3fb27SDimitry Andric } 32306c3fb27SDimitry Andric } 32406c3fb27SDimitry Andric } 32506c3fb27SDimitry Andric 32606c3fb27SDimitry Andric return true; 32706c3fb27SDimitry Andric } 32806c3fb27SDimitry Andric 32906c3fb27SDimitry Andric static bool hasAllWUsers(const MachineInstr &OrigMI, const RISCVSubtarget &ST, 33006c3fb27SDimitry Andric const MachineRegisterInfo &MRI) { 33106c3fb27SDimitry Andric return hasAllNBitUsers(OrigMI, ST, MRI, 32); 33206c3fb27SDimitry Andric } 33306c3fb27SDimitry Andric 33406c3fb27SDimitry Andric // This function returns true if the machine instruction always outputs a value 33506c3fb27SDimitry Andric // where bits 63:32 match bit 31. 33606c3fb27SDimitry Andric static bool isSignExtendingOpW(const MachineInstr &MI, 33706c3fb27SDimitry Andric const MachineRegisterInfo &MRI) { 33806c3fb27SDimitry Andric uint64_t TSFlags = MI.getDesc().TSFlags; 33906c3fb27SDimitry Andric 34006c3fb27SDimitry Andric // Instructions that can be determined from opcode are marked in tablegen. 34106c3fb27SDimitry Andric if (TSFlags & RISCVII::IsSignExtendingOpWMask) 34206c3fb27SDimitry Andric return true; 34306c3fb27SDimitry Andric 34406c3fb27SDimitry Andric // Special cases that require checking operands. 34506c3fb27SDimitry Andric switch (MI.getOpcode()) { 34606c3fb27SDimitry Andric // shifting right sufficiently makes the value 32-bit sign-extended 34706c3fb27SDimitry Andric case RISCV::SRAI: 34806c3fb27SDimitry Andric return MI.getOperand(2).getImm() >= 32; 34906c3fb27SDimitry Andric case RISCV::SRLI: 35006c3fb27SDimitry Andric return MI.getOperand(2).getImm() > 32; 35106c3fb27SDimitry Andric // The LI pattern ADDI rd, X0, imm is sign extended. 35206c3fb27SDimitry Andric case RISCV::ADDI: 35306c3fb27SDimitry Andric return MI.getOperand(1).isReg() && MI.getOperand(1).getReg() == RISCV::X0; 35406c3fb27SDimitry Andric // An ANDI with an 11 bit immediate will zero bits 63:11. 35506c3fb27SDimitry Andric case RISCV::ANDI: 35606c3fb27SDimitry Andric return isUInt<11>(MI.getOperand(2).getImm()); 35706c3fb27SDimitry Andric // An ORI with an >11 bit immediate (negative 12-bit) will set bits 63:11. 35806c3fb27SDimitry Andric case RISCV::ORI: 35906c3fb27SDimitry Andric return !isUInt<11>(MI.getOperand(2).getImm()); 360*5f757f3fSDimitry Andric // A bseti with X0 is sign extended if the immediate is less than 31. 361*5f757f3fSDimitry Andric case RISCV::BSETI: 362*5f757f3fSDimitry Andric return MI.getOperand(2).getImm() < 31 && 363*5f757f3fSDimitry Andric MI.getOperand(1).getReg() == RISCV::X0; 36406c3fb27SDimitry Andric // Copying from X0 produces zero. 36506c3fb27SDimitry Andric case RISCV::COPY: 36606c3fb27SDimitry Andric return MI.getOperand(1).getReg() == RISCV::X0; 367*5f757f3fSDimitry Andric case RISCV::PseudoAtomicLoadNand32: 368*5f757f3fSDimitry Andric return true; 369*5f757f3fSDimitry Andric case RISCV::PseudoVMV_X_S_MF8: 370*5f757f3fSDimitry Andric case RISCV::PseudoVMV_X_S_MF4: 371*5f757f3fSDimitry Andric case RISCV::PseudoVMV_X_S_MF2: 372*5f757f3fSDimitry Andric case RISCV::PseudoVMV_X_S_M1: 373*5f757f3fSDimitry Andric case RISCV::PseudoVMV_X_S_M2: 374*5f757f3fSDimitry Andric case RISCV::PseudoVMV_X_S_M4: 375*5f757f3fSDimitry Andric case RISCV::PseudoVMV_X_S_M8: { 376*5f757f3fSDimitry Andric // vmv.x.s has at least 33 sign bits if log2(sew) <= 5. 377*5f757f3fSDimitry Andric int64_t Log2SEW = MI.getOperand(2).getImm(); 378*5f757f3fSDimitry Andric assert(Log2SEW >= 3 && Log2SEW <= 6 && "Unexpected Log2SEW"); 379*5f757f3fSDimitry Andric return Log2SEW <= 5; 380*5f757f3fSDimitry Andric } 38106c3fb27SDimitry Andric } 38206c3fb27SDimitry Andric 38306c3fb27SDimitry Andric return false; 38406c3fb27SDimitry Andric } 38506c3fb27SDimitry Andric 38606c3fb27SDimitry Andric static bool isSignExtendedW(Register SrcReg, const RISCVSubtarget &ST, 38706c3fb27SDimitry Andric const MachineRegisterInfo &MRI, 38806c3fb27SDimitry Andric SmallPtrSetImpl<MachineInstr *> &FixableDef) { 38906c3fb27SDimitry Andric 39006c3fb27SDimitry Andric SmallPtrSet<const MachineInstr *, 4> Visited; 39106c3fb27SDimitry Andric SmallVector<MachineInstr *, 4> Worklist; 39206c3fb27SDimitry Andric 39306c3fb27SDimitry Andric auto AddRegDefToWorkList = [&](Register SrcReg) { 39406c3fb27SDimitry Andric if (!SrcReg.isVirtual()) 39506c3fb27SDimitry Andric return false; 39606c3fb27SDimitry Andric MachineInstr *SrcMI = MRI.getVRegDef(SrcReg); 39706c3fb27SDimitry Andric if (!SrcMI) 39806c3fb27SDimitry Andric return false; 399*5f757f3fSDimitry Andric // Code assumes the register is operand 0. 400*5f757f3fSDimitry Andric // TODO: Maybe the worklist should store register? 401*5f757f3fSDimitry Andric if (!SrcMI->getOperand(0).isReg() || 402*5f757f3fSDimitry Andric SrcMI->getOperand(0).getReg() != SrcReg) 403*5f757f3fSDimitry Andric return false; 40406c3fb27SDimitry Andric // Add SrcMI to the worklist. 40506c3fb27SDimitry Andric Worklist.push_back(SrcMI); 40606c3fb27SDimitry Andric return true; 40706c3fb27SDimitry Andric }; 40806c3fb27SDimitry Andric 40906c3fb27SDimitry Andric if (!AddRegDefToWorkList(SrcReg)) 41006c3fb27SDimitry Andric return false; 41106c3fb27SDimitry Andric 41206c3fb27SDimitry Andric while (!Worklist.empty()) { 41306c3fb27SDimitry Andric MachineInstr *MI = Worklist.pop_back_val(); 41406c3fb27SDimitry Andric 41506c3fb27SDimitry Andric // If we already visited this instruction, we don't need to check it again. 41606c3fb27SDimitry Andric if (!Visited.insert(MI).second) 41706c3fb27SDimitry Andric continue; 41806c3fb27SDimitry Andric 41906c3fb27SDimitry Andric // If this is a sign extending operation we don't need to look any further. 42006c3fb27SDimitry Andric if (isSignExtendingOpW(*MI, MRI)) 42106c3fb27SDimitry Andric continue; 42206c3fb27SDimitry Andric 42306c3fb27SDimitry Andric // Is this an instruction that propagates sign extend? 42406c3fb27SDimitry Andric switch (MI->getOpcode()) { 42506c3fb27SDimitry Andric default: 42606c3fb27SDimitry Andric // Unknown opcode, give up. 42706c3fb27SDimitry Andric return false; 42806c3fb27SDimitry Andric case RISCV::COPY: { 42906c3fb27SDimitry Andric const MachineFunction *MF = MI->getMF(); 43006c3fb27SDimitry Andric const RISCVMachineFunctionInfo *RVFI = 43106c3fb27SDimitry Andric MF->getInfo<RISCVMachineFunctionInfo>(); 43206c3fb27SDimitry Andric 43306c3fb27SDimitry Andric // If this is the entry block and the register is livein, see if we know 43406c3fb27SDimitry Andric // it is sign extended. 43506c3fb27SDimitry Andric if (MI->getParent() == &MF->front()) { 43606c3fb27SDimitry Andric Register VReg = MI->getOperand(0).getReg(); 43706c3fb27SDimitry Andric if (MF->getRegInfo().isLiveIn(VReg) && RVFI->isSExt32Register(VReg)) 43806c3fb27SDimitry Andric continue; 43906c3fb27SDimitry Andric } 44006c3fb27SDimitry Andric 44106c3fb27SDimitry Andric Register CopySrcReg = MI->getOperand(1).getReg(); 44206c3fb27SDimitry Andric if (CopySrcReg == RISCV::X10) { 44306c3fb27SDimitry Andric // For a method return value, we check the ZExt/SExt flags in attribute. 44406c3fb27SDimitry Andric // We assume the following code sequence for method call. 44506c3fb27SDimitry Andric // PseudoCALL @bar, ... 44606c3fb27SDimitry Andric // ADJCALLSTACKUP 0, 0, implicit-def dead $x2, implicit $x2 44706c3fb27SDimitry Andric // %0:gpr = COPY $x10 44806c3fb27SDimitry Andric // 44906c3fb27SDimitry Andric // We use the PseudoCall to look up the IR function being called to find 45006c3fb27SDimitry Andric // its return attributes. 45106c3fb27SDimitry Andric const MachineBasicBlock *MBB = MI->getParent(); 45206c3fb27SDimitry Andric auto II = MI->getIterator(); 45306c3fb27SDimitry Andric if (II == MBB->instr_begin() || 45406c3fb27SDimitry Andric (--II)->getOpcode() != RISCV::ADJCALLSTACKUP) 45506c3fb27SDimitry Andric return false; 45606c3fb27SDimitry Andric 45706c3fb27SDimitry Andric const MachineInstr &CallMI = *(--II); 45806c3fb27SDimitry Andric if (!CallMI.isCall() || !CallMI.getOperand(0).isGlobal()) 45906c3fb27SDimitry Andric return false; 46006c3fb27SDimitry Andric 46106c3fb27SDimitry Andric auto *CalleeFn = 46206c3fb27SDimitry Andric dyn_cast_if_present<Function>(CallMI.getOperand(0).getGlobal()); 46306c3fb27SDimitry Andric if (!CalleeFn) 46406c3fb27SDimitry Andric return false; 46506c3fb27SDimitry Andric 46606c3fb27SDimitry Andric auto *IntTy = dyn_cast<IntegerType>(CalleeFn->getReturnType()); 46706c3fb27SDimitry Andric if (!IntTy) 46806c3fb27SDimitry Andric return false; 46906c3fb27SDimitry Andric 47006c3fb27SDimitry Andric const AttributeSet &Attrs = CalleeFn->getAttributes().getRetAttrs(); 47106c3fb27SDimitry Andric unsigned BitWidth = IntTy->getBitWidth(); 47206c3fb27SDimitry Andric if ((BitWidth <= 32 && Attrs.hasAttribute(Attribute::SExt)) || 47306c3fb27SDimitry Andric (BitWidth < 32 && Attrs.hasAttribute(Attribute::ZExt))) 47406c3fb27SDimitry Andric continue; 47506c3fb27SDimitry Andric } 47606c3fb27SDimitry Andric 47706c3fb27SDimitry Andric if (!AddRegDefToWorkList(CopySrcReg)) 47806c3fb27SDimitry Andric return false; 47906c3fb27SDimitry Andric 48006c3fb27SDimitry Andric break; 48106c3fb27SDimitry Andric } 48206c3fb27SDimitry Andric 48306c3fb27SDimitry Andric // For these, we just need to check if the 1st operand is sign extended. 48406c3fb27SDimitry Andric case RISCV::BCLRI: 48506c3fb27SDimitry Andric case RISCV::BINVI: 48606c3fb27SDimitry Andric case RISCV::BSETI: 48706c3fb27SDimitry Andric if (MI->getOperand(2).getImm() >= 31) 48806c3fb27SDimitry Andric return false; 48906c3fb27SDimitry Andric [[fallthrough]]; 49006c3fb27SDimitry Andric case RISCV::REM: 49106c3fb27SDimitry Andric case RISCV::ANDI: 49206c3fb27SDimitry Andric case RISCV::ORI: 49306c3fb27SDimitry Andric case RISCV::XORI: 49406c3fb27SDimitry Andric // |Remainder| is always <= |Dividend|. If D is 32-bit, then so is R. 49506c3fb27SDimitry Andric // DIV doesn't work because of the edge case 0xf..f 8000 0000 / (long)-1 49606c3fb27SDimitry Andric // Logical operations use a sign extended 12-bit immediate. 49706c3fb27SDimitry Andric if (!AddRegDefToWorkList(MI->getOperand(1).getReg())) 49806c3fb27SDimitry Andric return false; 49906c3fb27SDimitry Andric 50006c3fb27SDimitry Andric break; 50106c3fb27SDimitry Andric case RISCV::PseudoCCADDW: 502*5f757f3fSDimitry Andric case RISCV::PseudoCCADDIW: 50306c3fb27SDimitry Andric case RISCV::PseudoCCSUBW: 504*5f757f3fSDimitry Andric case RISCV::PseudoCCSLLW: 505*5f757f3fSDimitry Andric case RISCV::PseudoCCSRLW: 506*5f757f3fSDimitry Andric case RISCV::PseudoCCSRAW: 507*5f757f3fSDimitry Andric case RISCV::PseudoCCSLLIW: 508*5f757f3fSDimitry Andric case RISCV::PseudoCCSRLIW: 509*5f757f3fSDimitry Andric case RISCV::PseudoCCSRAIW: 510*5f757f3fSDimitry Andric // Returns operand 4 or an ADDW/SUBW/etc. of operands 5 and 6. We only 511*5f757f3fSDimitry Andric // need to check if operand 4 is sign extended. 51206c3fb27SDimitry Andric if (!AddRegDefToWorkList(MI->getOperand(4).getReg())) 51306c3fb27SDimitry Andric return false; 51406c3fb27SDimitry Andric break; 51506c3fb27SDimitry Andric case RISCV::REMU: 51606c3fb27SDimitry Andric case RISCV::AND: 51706c3fb27SDimitry Andric case RISCV::OR: 51806c3fb27SDimitry Andric case RISCV::XOR: 51906c3fb27SDimitry Andric case RISCV::ANDN: 52006c3fb27SDimitry Andric case RISCV::ORN: 52106c3fb27SDimitry Andric case RISCV::XNOR: 52206c3fb27SDimitry Andric case RISCV::MAX: 52306c3fb27SDimitry Andric case RISCV::MAXU: 52406c3fb27SDimitry Andric case RISCV::MIN: 52506c3fb27SDimitry Andric case RISCV::MINU: 52606c3fb27SDimitry Andric case RISCV::PseudoCCMOVGPR: 52706c3fb27SDimitry Andric case RISCV::PseudoCCAND: 52806c3fb27SDimitry Andric case RISCV::PseudoCCOR: 52906c3fb27SDimitry Andric case RISCV::PseudoCCXOR: 53006c3fb27SDimitry Andric case RISCV::PHI: { 53106c3fb27SDimitry Andric // If all incoming values are sign-extended, the output of AND, OR, XOR, 53206c3fb27SDimitry Andric // MIN, MAX, or PHI is also sign-extended. 53306c3fb27SDimitry Andric 53406c3fb27SDimitry Andric // The input registers for PHI are operand 1, 3, ... 53506c3fb27SDimitry Andric // The input registers for PseudoCCMOVGPR are 4 and 5. 53606c3fb27SDimitry Andric // The input registers for PseudoCCAND/OR/XOR are 4, 5, and 6. 53706c3fb27SDimitry Andric // The input registers for others are operand 1 and 2. 53806c3fb27SDimitry Andric unsigned B = 1, E = 3, D = 1; 53906c3fb27SDimitry Andric switch (MI->getOpcode()) { 54006c3fb27SDimitry Andric case RISCV::PHI: 54106c3fb27SDimitry Andric E = MI->getNumOperands(); 54206c3fb27SDimitry Andric D = 2; 54306c3fb27SDimitry Andric break; 54406c3fb27SDimitry Andric case RISCV::PseudoCCMOVGPR: 54506c3fb27SDimitry Andric B = 4; 54606c3fb27SDimitry Andric E = 6; 54706c3fb27SDimitry Andric break; 54806c3fb27SDimitry Andric case RISCV::PseudoCCAND: 54906c3fb27SDimitry Andric case RISCV::PseudoCCOR: 55006c3fb27SDimitry Andric case RISCV::PseudoCCXOR: 55106c3fb27SDimitry Andric B = 4; 55206c3fb27SDimitry Andric E = 7; 55306c3fb27SDimitry Andric break; 55406c3fb27SDimitry Andric } 55506c3fb27SDimitry Andric 55606c3fb27SDimitry Andric for (unsigned I = B; I != E; I += D) { 55706c3fb27SDimitry Andric if (!MI->getOperand(I).isReg()) 55806c3fb27SDimitry Andric return false; 55906c3fb27SDimitry Andric 56006c3fb27SDimitry Andric if (!AddRegDefToWorkList(MI->getOperand(I).getReg())) 56106c3fb27SDimitry Andric return false; 56206c3fb27SDimitry Andric } 56306c3fb27SDimitry Andric 56406c3fb27SDimitry Andric break; 56506c3fb27SDimitry Andric } 56606c3fb27SDimitry Andric 567*5f757f3fSDimitry Andric case RISCV::CZERO_EQZ: 568*5f757f3fSDimitry Andric case RISCV::CZERO_NEZ: 56906c3fb27SDimitry Andric case RISCV::VT_MASKC: 57006c3fb27SDimitry Andric case RISCV::VT_MASKCN: 57106c3fb27SDimitry Andric // Instructions return zero or operand 1. Result is sign extended if 57206c3fb27SDimitry Andric // operand 1 is sign extended. 57306c3fb27SDimitry Andric if (!AddRegDefToWorkList(MI->getOperand(1).getReg())) 57406c3fb27SDimitry Andric return false; 57506c3fb27SDimitry Andric break; 57606c3fb27SDimitry Andric 57706c3fb27SDimitry Andric // With these opcode, we can "fix" them with the W-version 57806c3fb27SDimitry Andric // if we know all users of the result only rely on bits 31:0 57906c3fb27SDimitry Andric case RISCV::SLLI: 58006c3fb27SDimitry Andric // SLLIW reads the lowest 5 bits, while SLLI reads lowest 6 bits 58106c3fb27SDimitry Andric if (MI->getOperand(2).getImm() >= 32) 58206c3fb27SDimitry Andric return false; 58306c3fb27SDimitry Andric [[fallthrough]]; 58406c3fb27SDimitry Andric case RISCV::ADDI: 58506c3fb27SDimitry Andric case RISCV::ADD: 58606c3fb27SDimitry Andric case RISCV::LD: 58706c3fb27SDimitry Andric case RISCV::LWU: 58806c3fb27SDimitry Andric case RISCV::MUL: 58906c3fb27SDimitry Andric case RISCV::SUB: 59006c3fb27SDimitry Andric if (hasAllWUsers(*MI, ST, MRI)) { 59106c3fb27SDimitry Andric FixableDef.insert(MI); 59206c3fb27SDimitry Andric break; 59306c3fb27SDimitry Andric } 59406c3fb27SDimitry Andric return false; 59506c3fb27SDimitry Andric } 59606c3fb27SDimitry Andric } 59706c3fb27SDimitry Andric 59806c3fb27SDimitry Andric // If we get here, then every node we visited produces a sign extended value 59906c3fb27SDimitry Andric // or propagated sign extended values. So the result must be sign extended. 60006c3fb27SDimitry Andric return true; 60106c3fb27SDimitry Andric } 60206c3fb27SDimitry Andric 60306c3fb27SDimitry Andric static unsigned getWOp(unsigned Opcode) { 60406c3fb27SDimitry Andric switch (Opcode) { 60506c3fb27SDimitry Andric case RISCV::ADDI: 60606c3fb27SDimitry Andric return RISCV::ADDIW; 60706c3fb27SDimitry Andric case RISCV::ADD: 60806c3fb27SDimitry Andric return RISCV::ADDW; 60906c3fb27SDimitry Andric case RISCV::LD: 61006c3fb27SDimitry Andric case RISCV::LWU: 61106c3fb27SDimitry Andric return RISCV::LW; 61206c3fb27SDimitry Andric case RISCV::MUL: 61306c3fb27SDimitry Andric return RISCV::MULW; 61406c3fb27SDimitry Andric case RISCV::SLLI: 61506c3fb27SDimitry Andric return RISCV::SLLIW; 61606c3fb27SDimitry Andric case RISCV::SUB: 61706c3fb27SDimitry Andric return RISCV::SUBW; 61806c3fb27SDimitry Andric default: 61906c3fb27SDimitry Andric llvm_unreachable("Unexpected opcode for replacement with W variant"); 62006c3fb27SDimitry Andric } 62106c3fb27SDimitry Andric } 62206c3fb27SDimitry Andric 62306c3fb27SDimitry Andric bool RISCVOptWInstrs::removeSExtWInstrs(MachineFunction &MF, 62406c3fb27SDimitry Andric const RISCVInstrInfo &TII, 62506c3fb27SDimitry Andric const RISCVSubtarget &ST, 62606c3fb27SDimitry Andric MachineRegisterInfo &MRI) { 62706c3fb27SDimitry Andric if (DisableSExtWRemoval) 62806c3fb27SDimitry Andric return false; 62906c3fb27SDimitry Andric 63006c3fb27SDimitry Andric bool MadeChange = false; 63106c3fb27SDimitry Andric for (MachineBasicBlock &MBB : MF) { 632*5f757f3fSDimitry Andric for (MachineInstr &MI : llvm::make_early_inc_range(MBB)) { 63306c3fb27SDimitry Andric // We're looking for the sext.w pattern ADDIW rd, rs1, 0. 634*5f757f3fSDimitry Andric if (!RISCV::isSEXT_W(MI)) 63506c3fb27SDimitry Andric continue; 63606c3fb27SDimitry Andric 637*5f757f3fSDimitry Andric Register SrcReg = MI.getOperand(1).getReg(); 63806c3fb27SDimitry Andric 63906c3fb27SDimitry Andric SmallPtrSet<MachineInstr *, 4> FixableDefs; 64006c3fb27SDimitry Andric 64106c3fb27SDimitry Andric // If all users only use the lower bits, this sext.w is redundant. 64206c3fb27SDimitry Andric // Or if all definitions reaching MI sign-extend their output, 64306c3fb27SDimitry Andric // then sext.w is redundant. 644*5f757f3fSDimitry Andric if (!hasAllWUsers(MI, ST, MRI) && 64506c3fb27SDimitry Andric !isSignExtendedW(SrcReg, ST, MRI, FixableDefs)) 64606c3fb27SDimitry Andric continue; 64706c3fb27SDimitry Andric 648*5f757f3fSDimitry Andric Register DstReg = MI.getOperand(0).getReg(); 64906c3fb27SDimitry Andric if (!MRI.constrainRegClass(SrcReg, MRI.getRegClass(DstReg))) 65006c3fb27SDimitry Andric continue; 65106c3fb27SDimitry Andric 65206c3fb27SDimitry Andric // Convert Fixable instructions to their W versions. 65306c3fb27SDimitry Andric for (MachineInstr *Fixable : FixableDefs) { 65406c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << "Replacing " << *Fixable); 65506c3fb27SDimitry Andric Fixable->setDesc(TII.get(getWOp(Fixable->getOpcode()))); 65606c3fb27SDimitry Andric Fixable->clearFlag(MachineInstr::MIFlag::NoSWrap); 65706c3fb27SDimitry Andric Fixable->clearFlag(MachineInstr::MIFlag::NoUWrap); 65806c3fb27SDimitry Andric Fixable->clearFlag(MachineInstr::MIFlag::IsExact); 65906c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << " with " << *Fixable); 66006c3fb27SDimitry Andric ++NumTransformedToWInstrs; 66106c3fb27SDimitry Andric } 66206c3fb27SDimitry Andric 66306c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << "Removing redundant sign-extension\n"); 66406c3fb27SDimitry Andric MRI.replaceRegWith(DstReg, SrcReg); 66506c3fb27SDimitry Andric MRI.clearKillFlags(SrcReg); 666*5f757f3fSDimitry Andric MI.eraseFromParent(); 66706c3fb27SDimitry Andric ++NumRemovedSExtW; 66806c3fb27SDimitry Andric MadeChange = true; 66906c3fb27SDimitry Andric } 67006c3fb27SDimitry Andric } 67106c3fb27SDimitry Andric 67206c3fb27SDimitry Andric return MadeChange; 67306c3fb27SDimitry Andric } 67406c3fb27SDimitry Andric 67506c3fb27SDimitry Andric bool RISCVOptWInstrs::stripWSuffixes(MachineFunction &MF, 67606c3fb27SDimitry Andric const RISCVInstrInfo &TII, 67706c3fb27SDimitry Andric const RISCVSubtarget &ST, 67806c3fb27SDimitry Andric MachineRegisterInfo &MRI) { 67906c3fb27SDimitry Andric if (DisableStripWSuffix) 68006c3fb27SDimitry Andric return false; 68106c3fb27SDimitry Andric 68206c3fb27SDimitry Andric bool MadeChange = false; 68306c3fb27SDimitry Andric for (MachineBasicBlock &MBB : MF) { 684*5f757f3fSDimitry Andric for (MachineInstr &MI : MBB) { 68506c3fb27SDimitry Andric unsigned Opc; 68606c3fb27SDimitry Andric switch (MI.getOpcode()) { 68706c3fb27SDimitry Andric default: 68806c3fb27SDimitry Andric continue; 68906c3fb27SDimitry Andric case RISCV::ADDW: Opc = RISCV::ADD; break; 690*5f757f3fSDimitry Andric case RISCV::ADDIW: Opc = RISCV::ADDI; break; 69106c3fb27SDimitry Andric case RISCV::MULW: Opc = RISCV::MUL; break; 69206c3fb27SDimitry Andric case RISCV::SLLIW: Opc = RISCV::SLLI; break; 69306c3fb27SDimitry Andric } 69406c3fb27SDimitry Andric 69506c3fb27SDimitry Andric if (hasAllWUsers(MI, ST, MRI)) { 69606c3fb27SDimitry Andric MI.setDesc(TII.get(Opc)); 69706c3fb27SDimitry Andric MadeChange = true; 69806c3fb27SDimitry Andric } 69906c3fb27SDimitry Andric } 70006c3fb27SDimitry Andric } 70106c3fb27SDimitry Andric 70206c3fb27SDimitry Andric return MadeChange; 70306c3fb27SDimitry Andric } 70406c3fb27SDimitry Andric 70506c3fb27SDimitry Andric bool RISCVOptWInstrs::runOnMachineFunction(MachineFunction &MF) { 70606c3fb27SDimitry Andric if (skipFunction(MF.getFunction())) 70706c3fb27SDimitry Andric return false; 70806c3fb27SDimitry Andric 70906c3fb27SDimitry Andric MachineRegisterInfo &MRI = MF.getRegInfo(); 71006c3fb27SDimitry Andric const RISCVSubtarget &ST = MF.getSubtarget<RISCVSubtarget>(); 71106c3fb27SDimitry Andric const RISCVInstrInfo &TII = *ST.getInstrInfo(); 71206c3fb27SDimitry Andric 71306c3fb27SDimitry Andric if (!ST.is64Bit()) 71406c3fb27SDimitry Andric return false; 71506c3fb27SDimitry Andric 71606c3fb27SDimitry Andric bool MadeChange = false; 71706c3fb27SDimitry Andric MadeChange |= removeSExtWInstrs(MF, TII, ST, MRI); 71806c3fb27SDimitry Andric MadeChange |= stripWSuffixes(MF, TII, ST, MRI); 71906c3fb27SDimitry Andric 72006c3fb27SDimitry Andric return MadeChange; 72106c3fb27SDimitry Andric } 722