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 129*1db9f3b2SDimitry Andric Register DestReg = MI->getOperand(0).getReg(); 130*1db9f3b2SDimitry Andric if (!DestReg.isVirtual()) 131*1db9f3b2SDimitry Andric return false; 132*1db9f3b2SDimitry Andric 133*1db9f3b2SDimitry 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; 3735f757f3fSDimitry Andric case RISCV::PseudoVMV_X_S_MF8: 3745f757f3fSDimitry Andric case RISCV::PseudoVMV_X_S_MF4: 3755f757f3fSDimitry Andric case RISCV::PseudoVMV_X_S_MF2: 3765f757f3fSDimitry Andric case RISCV::PseudoVMV_X_S_M1: 3775f757f3fSDimitry Andric case RISCV::PseudoVMV_X_S_M2: 3785f757f3fSDimitry Andric case RISCV::PseudoVMV_X_S_M4: 3795f757f3fSDimitry Andric case RISCV::PseudoVMV_X_S_M8: { 3805f757f3fSDimitry Andric // vmv.x.s has at least 33 sign bits if log2(sew) <= 5. 3815f757f3fSDimitry Andric int64_t Log2SEW = MI.getOperand(2).getImm(); 3825f757f3fSDimitry Andric assert(Log2SEW >= 3 && Log2SEW <= 6 && "Unexpected Log2SEW"); 3835f757f3fSDimitry Andric return Log2SEW <= 5; 3845f757f3fSDimitry Andric } 38506c3fb27SDimitry Andric } 38606c3fb27SDimitry Andric 38706c3fb27SDimitry Andric return false; 38806c3fb27SDimitry Andric } 38906c3fb27SDimitry Andric 39006c3fb27SDimitry Andric static bool isSignExtendedW(Register SrcReg, const RISCVSubtarget &ST, 39106c3fb27SDimitry Andric const MachineRegisterInfo &MRI, 39206c3fb27SDimitry Andric SmallPtrSetImpl<MachineInstr *> &FixableDef) { 39306c3fb27SDimitry Andric 39406c3fb27SDimitry Andric SmallPtrSet<const MachineInstr *, 4> Visited; 39506c3fb27SDimitry Andric SmallVector<MachineInstr *, 4> Worklist; 39606c3fb27SDimitry Andric 39706c3fb27SDimitry Andric auto AddRegDefToWorkList = [&](Register SrcReg) { 39806c3fb27SDimitry Andric if (!SrcReg.isVirtual()) 39906c3fb27SDimitry Andric return false; 40006c3fb27SDimitry Andric MachineInstr *SrcMI = MRI.getVRegDef(SrcReg); 40106c3fb27SDimitry Andric if (!SrcMI) 40206c3fb27SDimitry Andric return false; 4035f757f3fSDimitry Andric // Code assumes the register is operand 0. 4045f757f3fSDimitry Andric // TODO: Maybe the worklist should store register? 4055f757f3fSDimitry Andric if (!SrcMI->getOperand(0).isReg() || 4065f757f3fSDimitry Andric SrcMI->getOperand(0).getReg() != SrcReg) 4075f757f3fSDimitry Andric return false; 40806c3fb27SDimitry Andric // Add SrcMI to the worklist. 40906c3fb27SDimitry Andric Worklist.push_back(SrcMI); 41006c3fb27SDimitry Andric return true; 41106c3fb27SDimitry Andric }; 41206c3fb27SDimitry Andric 41306c3fb27SDimitry Andric if (!AddRegDefToWorkList(SrcReg)) 41406c3fb27SDimitry Andric return false; 41506c3fb27SDimitry Andric 41606c3fb27SDimitry Andric while (!Worklist.empty()) { 41706c3fb27SDimitry Andric MachineInstr *MI = Worklist.pop_back_val(); 41806c3fb27SDimitry Andric 41906c3fb27SDimitry Andric // If we already visited this instruction, we don't need to check it again. 42006c3fb27SDimitry Andric if (!Visited.insert(MI).second) 42106c3fb27SDimitry Andric continue; 42206c3fb27SDimitry Andric 42306c3fb27SDimitry Andric // If this is a sign extending operation we don't need to look any further. 42406c3fb27SDimitry Andric if (isSignExtendingOpW(*MI, MRI)) 42506c3fb27SDimitry Andric continue; 42606c3fb27SDimitry Andric 42706c3fb27SDimitry Andric // Is this an instruction that propagates sign extend? 42806c3fb27SDimitry Andric switch (MI->getOpcode()) { 42906c3fb27SDimitry Andric default: 43006c3fb27SDimitry Andric // Unknown opcode, give up. 43106c3fb27SDimitry Andric return false; 43206c3fb27SDimitry Andric case RISCV::COPY: { 43306c3fb27SDimitry Andric const MachineFunction *MF = MI->getMF(); 43406c3fb27SDimitry Andric const RISCVMachineFunctionInfo *RVFI = 43506c3fb27SDimitry Andric MF->getInfo<RISCVMachineFunctionInfo>(); 43606c3fb27SDimitry Andric 43706c3fb27SDimitry Andric // If this is the entry block and the register is livein, see if we know 43806c3fb27SDimitry Andric // it is sign extended. 43906c3fb27SDimitry Andric if (MI->getParent() == &MF->front()) { 44006c3fb27SDimitry Andric Register VReg = MI->getOperand(0).getReg(); 44106c3fb27SDimitry Andric if (MF->getRegInfo().isLiveIn(VReg) && RVFI->isSExt32Register(VReg)) 44206c3fb27SDimitry Andric continue; 44306c3fb27SDimitry Andric } 44406c3fb27SDimitry Andric 44506c3fb27SDimitry Andric Register CopySrcReg = MI->getOperand(1).getReg(); 44606c3fb27SDimitry Andric if (CopySrcReg == RISCV::X10) { 44706c3fb27SDimitry Andric // For a method return value, we check the ZExt/SExt flags in attribute. 44806c3fb27SDimitry Andric // We assume the following code sequence for method call. 44906c3fb27SDimitry Andric // PseudoCALL @bar, ... 45006c3fb27SDimitry Andric // ADJCALLSTACKUP 0, 0, implicit-def dead $x2, implicit $x2 45106c3fb27SDimitry Andric // %0:gpr = COPY $x10 45206c3fb27SDimitry Andric // 45306c3fb27SDimitry Andric // We use the PseudoCall to look up the IR function being called to find 45406c3fb27SDimitry Andric // its return attributes. 45506c3fb27SDimitry Andric const MachineBasicBlock *MBB = MI->getParent(); 45606c3fb27SDimitry Andric auto II = MI->getIterator(); 45706c3fb27SDimitry Andric if (II == MBB->instr_begin() || 45806c3fb27SDimitry Andric (--II)->getOpcode() != RISCV::ADJCALLSTACKUP) 45906c3fb27SDimitry Andric return false; 46006c3fb27SDimitry Andric 46106c3fb27SDimitry Andric const MachineInstr &CallMI = *(--II); 46206c3fb27SDimitry Andric if (!CallMI.isCall() || !CallMI.getOperand(0).isGlobal()) 46306c3fb27SDimitry Andric return false; 46406c3fb27SDimitry Andric 46506c3fb27SDimitry Andric auto *CalleeFn = 46606c3fb27SDimitry Andric dyn_cast_if_present<Function>(CallMI.getOperand(0).getGlobal()); 46706c3fb27SDimitry Andric if (!CalleeFn) 46806c3fb27SDimitry Andric return false; 46906c3fb27SDimitry Andric 47006c3fb27SDimitry Andric auto *IntTy = dyn_cast<IntegerType>(CalleeFn->getReturnType()); 47106c3fb27SDimitry Andric if (!IntTy) 47206c3fb27SDimitry Andric return false; 47306c3fb27SDimitry Andric 47406c3fb27SDimitry Andric const AttributeSet &Attrs = CalleeFn->getAttributes().getRetAttrs(); 47506c3fb27SDimitry Andric unsigned BitWidth = IntTy->getBitWidth(); 47606c3fb27SDimitry Andric if ((BitWidth <= 32 && Attrs.hasAttribute(Attribute::SExt)) || 47706c3fb27SDimitry Andric (BitWidth < 32 && Attrs.hasAttribute(Attribute::ZExt))) 47806c3fb27SDimitry Andric continue; 47906c3fb27SDimitry Andric } 48006c3fb27SDimitry Andric 48106c3fb27SDimitry Andric if (!AddRegDefToWorkList(CopySrcReg)) 48206c3fb27SDimitry Andric return false; 48306c3fb27SDimitry Andric 48406c3fb27SDimitry Andric break; 48506c3fb27SDimitry Andric } 48606c3fb27SDimitry Andric 48706c3fb27SDimitry Andric // For these, we just need to check if the 1st operand is sign extended. 48806c3fb27SDimitry Andric case RISCV::BCLRI: 48906c3fb27SDimitry Andric case RISCV::BINVI: 49006c3fb27SDimitry Andric case RISCV::BSETI: 49106c3fb27SDimitry Andric if (MI->getOperand(2).getImm() >= 31) 49206c3fb27SDimitry Andric return false; 49306c3fb27SDimitry Andric [[fallthrough]]; 49406c3fb27SDimitry Andric case RISCV::REM: 49506c3fb27SDimitry Andric case RISCV::ANDI: 49606c3fb27SDimitry Andric case RISCV::ORI: 49706c3fb27SDimitry Andric case RISCV::XORI: 49806c3fb27SDimitry Andric // |Remainder| is always <= |Dividend|. If D is 32-bit, then so is R. 49906c3fb27SDimitry Andric // DIV doesn't work because of the edge case 0xf..f 8000 0000 / (long)-1 50006c3fb27SDimitry Andric // Logical operations use a sign extended 12-bit immediate. 50106c3fb27SDimitry Andric if (!AddRegDefToWorkList(MI->getOperand(1).getReg())) 50206c3fb27SDimitry Andric return false; 50306c3fb27SDimitry Andric 50406c3fb27SDimitry Andric break; 50506c3fb27SDimitry Andric case RISCV::PseudoCCADDW: 5065f757f3fSDimitry Andric case RISCV::PseudoCCADDIW: 50706c3fb27SDimitry Andric case RISCV::PseudoCCSUBW: 5085f757f3fSDimitry Andric case RISCV::PseudoCCSLLW: 5095f757f3fSDimitry Andric case RISCV::PseudoCCSRLW: 5105f757f3fSDimitry Andric case RISCV::PseudoCCSRAW: 5115f757f3fSDimitry Andric case RISCV::PseudoCCSLLIW: 5125f757f3fSDimitry Andric case RISCV::PseudoCCSRLIW: 5135f757f3fSDimitry Andric case RISCV::PseudoCCSRAIW: 5145f757f3fSDimitry Andric // Returns operand 4 or an ADDW/SUBW/etc. of operands 5 and 6. We only 5155f757f3fSDimitry Andric // need to check if operand 4 is sign extended. 51606c3fb27SDimitry Andric if (!AddRegDefToWorkList(MI->getOperand(4).getReg())) 51706c3fb27SDimitry Andric return false; 51806c3fb27SDimitry Andric break; 51906c3fb27SDimitry Andric case RISCV::REMU: 52006c3fb27SDimitry Andric case RISCV::AND: 52106c3fb27SDimitry Andric case RISCV::OR: 52206c3fb27SDimitry Andric case RISCV::XOR: 52306c3fb27SDimitry Andric case RISCV::ANDN: 52406c3fb27SDimitry Andric case RISCV::ORN: 52506c3fb27SDimitry Andric case RISCV::XNOR: 52606c3fb27SDimitry Andric case RISCV::MAX: 52706c3fb27SDimitry Andric case RISCV::MAXU: 52806c3fb27SDimitry Andric case RISCV::MIN: 52906c3fb27SDimitry Andric case RISCV::MINU: 53006c3fb27SDimitry Andric case RISCV::PseudoCCMOVGPR: 53106c3fb27SDimitry Andric case RISCV::PseudoCCAND: 53206c3fb27SDimitry Andric case RISCV::PseudoCCOR: 53306c3fb27SDimitry Andric case RISCV::PseudoCCXOR: 53406c3fb27SDimitry Andric case RISCV::PHI: { 53506c3fb27SDimitry Andric // If all incoming values are sign-extended, the output of AND, OR, XOR, 53606c3fb27SDimitry Andric // MIN, MAX, or PHI is also sign-extended. 53706c3fb27SDimitry Andric 53806c3fb27SDimitry Andric // The input registers for PHI are operand 1, 3, ... 53906c3fb27SDimitry Andric // The input registers for PseudoCCMOVGPR are 4 and 5. 54006c3fb27SDimitry Andric // The input registers for PseudoCCAND/OR/XOR are 4, 5, and 6. 54106c3fb27SDimitry Andric // The input registers for others are operand 1 and 2. 54206c3fb27SDimitry Andric unsigned B = 1, E = 3, D = 1; 54306c3fb27SDimitry Andric switch (MI->getOpcode()) { 54406c3fb27SDimitry Andric case RISCV::PHI: 54506c3fb27SDimitry Andric E = MI->getNumOperands(); 54606c3fb27SDimitry Andric D = 2; 54706c3fb27SDimitry Andric break; 54806c3fb27SDimitry Andric case RISCV::PseudoCCMOVGPR: 54906c3fb27SDimitry Andric B = 4; 55006c3fb27SDimitry Andric E = 6; 55106c3fb27SDimitry Andric break; 55206c3fb27SDimitry Andric case RISCV::PseudoCCAND: 55306c3fb27SDimitry Andric case RISCV::PseudoCCOR: 55406c3fb27SDimitry Andric case RISCV::PseudoCCXOR: 55506c3fb27SDimitry Andric B = 4; 55606c3fb27SDimitry Andric E = 7; 55706c3fb27SDimitry Andric break; 55806c3fb27SDimitry Andric } 55906c3fb27SDimitry Andric 56006c3fb27SDimitry Andric for (unsigned I = B; I != E; I += D) { 56106c3fb27SDimitry Andric if (!MI->getOperand(I).isReg()) 56206c3fb27SDimitry Andric return false; 56306c3fb27SDimitry Andric 56406c3fb27SDimitry Andric if (!AddRegDefToWorkList(MI->getOperand(I).getReg())) 56506c3fb27SDimitry Andric return false; 56606c3fb27SDimitry Andric } 56706c3fb27SDimitry Andric 56806c3fb27SDimitry Andric break; 56906c3fb27SDimitry Andric } 57006c3fb27SDimitry Andric 5715f757f3fSDimitry Andric case RISCV::CZERO_EQZ: 5725f757f3fSDimitry Andric case RISCV::CZERO_NEZ: 57306c3fb27SDimitry Andric case RISCV::VT_MASKC: 57406c3fb27SDimitry Andric case RISCV::VT_MASKCN: 57506c3fb27SDimitry Andric // Instructions return zero or operand 1. Result is sign extended if 57606c3fb27SDimitry Andric // operand 1 is sign extended. 57706c3fb27SDimitry Andric if (!AddRegDefToWorkList(MI->getOperand(1).getReg())) 57806c3fb27SDimitry Andric return false; 57906c3fb27SDimitry Andric break; 58006c3fb27SDimitry Andric 58106c3fb27SDimitry Andric // With these opcode, we can "fix" them with the W-version 58206c3fb27SDimitry Andric // if we know all users of the result only rely on bits 31:0 58306c3fb27SDimitry Andric case RISCV::SLLI: 58406c3fb27SDimitry Andric // SLLIW reads the lowest 5 bits, while SLLI reads lowest 6 bits 58506c3fb27SDimitry Andric if (MI->getOperand(2).getImm() >= 32) 58606c3fb27SDimitry Andric return false; 58706c3fb27SDimitry Andric [[fallthrough]]; 58806c3fb27SDimitry Andric case RISCV::ADDI: 58906c3fb27SDimitry Andric case RISCV::ADD: 59006c3fb27SDimitry Andric case RISCV::LD: 59106c3fb27SDimitry Andric case RISCV::LWU: 59206c3fb27SDimitry Andric case RISCV::MUL: 59306c3fb27SDimitry Andric case RISCV::SUB: 59406c3fb27SDimitry Andric if (hasAllWUsers(*MI, ST, MRI)) { 59506c3fb27SDimitry Andric FixableDef.insert(MI); 59606c3fb27SDimitry Andric break; 59706c3fb27SDimitry Andric } 59806c3fb27SDimitry Andric return false; 59906c3fb27SDimitry Andric } 60006c3fb27SDimitry Andric } 60106c3fb27SDimitry Andric 60206c3fb27SDimitry Andric // If we get here, then every node we visited produces a sign extended value 60306c3fb27SDimitry Andric // or propagated sign extended values. So the result must be sign extended. 60406c3fb27SDimitry Andric return true; 60506c3fb27SDimitry Andric } 60606c3fb27SDimitry Andric 60706c3fb27SDimitry Andric static unsigned getWOp(unsigned Opcode) { 60806c3fb27SDimitry Andric switch (Opcode) { 60906c3fb27SDimitry Andric case RISCV::ADDI: 61006c3fb27SDimitry Andric return RISCV::ADDIW; 61106c3fb27SDimitry Andric case RISCV::ADD: 61206c3fb27SDimitry Andric return RISCV::ADDW; 61306c3fb27SDimitry Andric case RISCV::LD: 61406c3fb27SDimitry Andric case RISCV::LWU: 61506c3fb27SDimitry Andric return RISCV::LW; 61606c3fb27SDimitry Andric case RISCV::MUL: 61706c3fb27SDimitry Andric return RISCV::MULW; 61806c3fb27SDimitry Andric case RISCV::SLLI: 61906c3fb27SDimitry Andric return RISCV::SLLIW; 62006c3fb27SDimitry Andric case RISCV::SUB: 62106c3fb27SDimitry Andric return RISCV::SUBW; 62206c3fb27SDimitry Andric default: 62306c3fb27SDimitry Andric llvm_unreachable("Unexpected opcode for replacement with W variant"); 62406c3fb27SDimitry Andric } 62506c3fb27SDimitry Andric } 62606c3fb27SDimitry Andric 62706c3fb27SDimitry Andric bool RISCVOptWInstrs::removeSExtWInstrs(MachineFunction &MF, 62806c3fb27SDimitry Andric const RISCVInstrInfo &TII, 62906c3fb27SDimitry Andric const RISCVSubtarget &ST, 63006c3fb27SDimitry Andric MachineRegisterInfo &MRI) { 63106c3fb27SDimitry Andric if (DisableSExtWRemoval) 63206c3fb27SDimitry Andric return false; 63306c3fb27SDimitry Andric 63406c3fb27SDimitry Andric bool MadeChange = false; 63506c3fb27SDimitry Andric for (MachineBasicBlock &MBB : MF) { 6365f757f3fSDimitry Andric for (MachineInstr &MI : llvm::make_early_inc_range(MBB)) { 63706c3fb27SDimitry Andric // We're looking for the sext.w pattern ADDIW rd, rs1, 0. 6385f757f3fSDimitry Andric if (!RISCV::isSEXT_W(MI)) 63906c3fb27SDimitry Andric continue; 64006c3fb27SDimitry Andric 6415f757f3fSDimitry Andric Register SrcReg = MI.getOperand(1).getReg(); 64206c3fb27SDimitry Andric 64306c3fb27SDimitry Andric SmallPtrSet<MachineInstr *, 4> FixableDefs; 64406c3fb27SDimitry Andric 64506c3fb27SDimitry Andric // If all users only use the lower bits, this sext.w is redundant. 64606c3fb27SDimitry Andric // Or if all definitions reaching MI sign-extend their output, 64706c3fb27SDimitry Andric // then sext.w is redundant. 6485f757f3fSDimitry Andric if (!hasAllWUsers(MI, ST, MRI) && 64906c3fb27SDimitry Andric !isSignExtendedW(SrcReg, ST, MRI, FixableDefs)) 65006c3fb27SDimitry Andric continue; 65106c3fb27SDimitry Andric 6525f757f3fSDimitry Andric Register DstReg = MI.getOperand(0).getReg(); 65306c3fb27SDimitry Andric if (!MRI.constrainRegClass(SrcReg, MRI.getRegClass(DstReg))) 65406c3fb27SDimitry Andric continue; 65506c3fb27SDimitry Andric 65606c3fb27SDimitry Andric // Convert Fixable instructions to their W versions. 65706c3fb27SDimitry Andric for (MachineInstr *Fixable : FixableDefs) { 65806c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << "Replacing " << *Fixable); 65906c3fb27SDimitry Andric Fixable->setDesc(TII.get(getWOp(Fixable->getOpcode()))); 66006c3fb27SDimitry Andric Fixable->clearFlag(MachineInstr::MIFlag::NoSWrap); 66106c3fb27SDimitry Andric Fixable->clearFlag(MachineInstr::MIFlag::NoUWrap); 66206c3fb27SDimitry Andric Fixable->clearFlag(MachineInstr::MIFlag::IsExact); 66306c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << " with " << *Fixable); 66406c3fb27SDimitry Andric ++NumTransformedToWInstrs; 66506c3fb27SDimitry Andric } 66606c3fb27SDimitry Andric 66706c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << "Removing redundant sign-extension\n"); 66806c3fb27SDimitry Andric MRI.replaceRegWith(DstReg, SrcReg); 66906c3fb27SDimitry Andric MRI.clearKillFlags(SrcReg); 6705f757f3fSDimitry Andric MI.eraseFromParent(); 67106c3fb27SDimitry Andric ++NumRemovedSExtW; 67206c3fb27SDimitry Andric MadeChange = true; 67306c3fb27SDimitry Andric } 67406c3fb27SDimitry Andric } 67506c3fb27SDimitry Andric 67606c3fb27SDimitry Andric return MadeChange; 67706c3fb27SDimitry Andric } 67806c3fb27SDimitry Andric 67906c3fb27SDimitry Andric bool RISCVOptWInstrs::stripWSuffixes(MachineFunction &MF, 68006c3fb27SDimitry Andric const RISCVInstrInfo &TII, 68106c3fb27SDimitry Andric const RISCVSubtarget &ST, 68206c3fb27SDimitry Andric MachineRegisterInfo &MRI) { 68306c3fb27SDimitry Andric if (DisableStripWSuffix) 68406c3fb27SDimitry Andric return false; 68506c3fb27SDimitry Andric 68606c3fb27SDimitry Andric bool MadeChange = false; 68706c3fb27SDimitry Andric for (MachineBasicBlock &MBB : MF) { 6885f757f3fSDimitry Andric for (MachineInstr &MI : MBB) { 68906c3fb27SDimitry Andric unsigned Opc; 69006c3fb27SDimitry Andric switch (MI.getOpcode()) { 69106c3fb27SDimitry Andric default: 69206c3fb27SDimitry Andric continue; 69306c3fb27SDimitry Andric case RISCV::ADDW: Opc = RISCV::ADD; break; 6945f757f3fSDimitry Andric case RISCV::ADDIW: Opc = RISCV::ADDI; break; 69506c3fb27SDimitry Andric case RISCV::MULW: Opc = RISCV::MUL; break; 69606c3fb27SDimitry Andric case RISCV::SLLIW: Opc = RISCV::SLLI; break; 69706c3fb27SDimitry Andric } 69806c3fb27SDimitry Andric 69906c3fb27SDimitry Andric if (hasAllWUsers(MI, ST, MRI)) { 70006c3fb27SDimitry Andric MI.setDesc(TII.get(Opc)); 70106c3fb27SDimitry Andric MadeChange = true; 70206c3fb27SDimitry Andric } 70306c3fb27SDimitry Andric } 70406c3fb27SDimitry Andric } 70506c3fb27SDimitry Andric 70606c3fb27SDimitry Andric return MadeChange; 70706c3fb27SDimitry Andric } 70806c3fb27SDimitry Andric 70906c3fb27SDimitry Andric bool RISCVOptWInstrs::runOnMachineFunction(MachineFunction &MF) { 71006c3fb27SDimitry Andric if (skipFunction(MF.getFunction())) 71106c3fb27SDimitry Andric return false; 71206c3fb27SDimitry Andric 71306c3fb27SDimitry Andric MachineRegisterInfo &MRI = MF.getRegInfo(); 71406c3fb27SDimitry Andric const RISCVSubtarget &ST = MF.getSubtarget<RISCVSubtarget>(); 71506c3fb27SDimitry Andric const RISCVInstrInfo &TII = *ST.getInstrInfo(); 71606c3fb27SDimitry Andric 71706c3fb27SDimitry Andric if (!ST.is64Bit()) 71806c3fb27SDimitry Andric return false; 71906c3fb27SDimitry Andric 72006c3fb27SDimitry Andric bool MadeChange = false; 72106c3fb27SDimitry Andric MadeChange |= removeSExtWInstrs(MF, TII, ST, MRI); 72206c3fb27SDimitry Andric MadeChange |= stripWSuffixes(MF, TII, ST, MRI); 72306c3fb27SDimitry Andric 72406c3fb27SDimitry Andric return MadeChange; 72506c3fb27SDimitry Andric } 726