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