217 lines · cpp
1//=== RISCVPostLegalizerCombiner.cpp --------------------------*- C++ -*-===//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/// \file10/// Post-legalization combines on generic MachineInstrs.11///12/// The combines here must preserve instruction legality.13///14/// Combines which don't rely on instruction legality should go in the15/// RISCVPreLegalizerCombiner.16///17//===----------------------------------------------------------------------===//18 19#include "RISCVTargetMachine.h"20#include "llvm/CodeGen/GlobalISel/CSEInfo.h"21#include "llvm/CodeGen/GlobalISel/Combiner.h"22#include "llvm/CodeGen/GlobalISel/CombinerHelper.h"23#include "llvm/CodeGen/GlobalISel/CombinerInfo.h"24#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"25#include "llvm/CodeGen/GlobalISel/GISelValueTracking.h"26#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"27#include "llvm/CodeGen/MachineDominators.h"28#include "llvm/CodeGen/MachineFunctionPass.h"29#include "llvm/CodeGen/TargetPassConfig.h"30#include "llvm/Support/FormatVariadic.h"31 32#define GET_GICOMBINER_DEPS33#include "RISCVGenPostLegalizeGICombiner.inc"34#undef GET_GICOMBINER_DEPS35 36#define DEBUG_TYPE "riscv-postlegalizer-combiner"37 38using namespace llvm;39 40namespace {41 42#define GET_GICOMBINER_TYPES43#include "RISCVGenPostLegalizeGICombiner.inc"44#undef GET_GICOMBINER_TYPES45 46/// Match: G_STORE (G_FCONSTANT +0.0), addr47/// Return the source vreg in MatchInfo if matched.48bool matchFoldFPZeroStore(MachineInstr &MI, MachineRegisterInfo &MRI,49 const RISCVSubtarget &STI, Register &MatchInfo) {50 if (MI.getOpcode() != TargetOpcode::G_STORE)51 return false;52 53 Register SrcReg = MI.getOperand(0).getReg();54 if (!SrcReg.isVirtual())55 return false;56 57 MachineInstr *Def = MRI.getVRegDef(SrcReg);58 if (!Def || Def->getOpcode() != TargetOpcode::G_FCONSTANT)59 return false;60 61 auto *CFP = Def->getOperand(1).getFPImm();62 if (!CFP || !CFP->getValueAPF().isPosZero())63 return false;64 65 unsigned ValBits = MRI.getType(SrcReg).getSizeInBits();66 if ((ValBits == 16 && !STI.hasStdExtZfh()) ||67 (ValBits == 32 && !STI.hasStdExtF()) ||68 (ValBits == 64 && (!STI.hasStdExtD() || !STI.is64Bit())))69 return false;70 71 MatchInfo = SrcReg;72 return true;73}74 75/// Apply: rewrite to G_STORE (G_CONSTANT 0 [XLEN]), addr76void applyFoldFPZeroStore(MachineInstr &MI, MachineRegisterInfo &MRI,77 MachineIRBuilder &B, const RISCVSubtarget &STI,78 Register &MatchInfo) {79 const unsigned XLen = STI.getXLen();80 81 auto Zero = B.buildConstant(LLT::scalar(XLen), 0);82 MI.getOperand(0).setReg(Zero.getReg(0));83 84 MachineInstr *Def = MRI.getVRegDef(MatchInfo);85 if (Def && MRI.use_nodbg_empty(MatchInfo))86 Def->eraseFromParent();87 88#ifndef NDEBUG89 unsigned ValBits = MRI.getType(MatchInfo).getSizeInBits();90 LLVM_DEBUG(dbgs() << formatv("[{0}] Fold FP zero store -> int zero "91 "(XLEN={1}, ValBits={2}):\n {3}\n",92 DEBUG_TYPE, XLen, ValBits, MI));93#endif94}95 96class RISCVPostLegalizerCombinerImpl : public Combiner {97protected:98 const CombinerHelper Helper;99 const RISCVPostLegalizerCombinerImplRuleConfig &RuleConfig;100 const RISCVSubtarget &STI;101 102public:103 RISCVPostLegalizerCombinerImpl(104 MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC,105 GISelValueTracking &VT, GISelCSEInfo *CSEInfo,106 const RISCVPostLegalizerCombinerImplRuleConfig &RuleConfig,107 const RISCVSubtarget &STI, MachineDominatorTree *MDT,108 const LegalizerInfo *LI);109 110 static const char *getName() { return "RISCVPostLegalizerCombiner"; }111 112 bool tryCombineAll(MachineInstr &I) const override;113 114private:115#define GET_GICOMBINER_CLASS_MEMBERS116#include "RISCVGenPostLegalizeGICombiner.inc"117#undef GET_GICOMBINER_CLASS_MEMBERS118};119 120#define GET_GICOMBINER_IMPL121#include "RISCVGenPostLegalizeGICombiner.inc"122#undef GET_GICOMBINER_IMPL123 124RISCVPostLegalizerCombinerImpl::RISCVPostLegalizerCombinerImpl(125 MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC,126 GISelValueTracking &VT, GISelCSEInfo *CSEInfo,127 const RISCVPostLegalizerCombinerImplRuleConfig &RuleConfig,128 const RISCVSubtarget &STI, MachineDominatorTree *MDT,129 const LegalizerInfo *LI)130 : Combiner(MF, CInfo, TPC, &VT, CSEInfo),131 Helper(Observer, B, /*IsPreLegalize*/ false, &VT, MDT, LI),132 RuleConfig(RuleConfig), STI(STI),133#define GET_GICOMBINER_CONSTRUCTOR_INITS134#include "RISCVGenPostLegalizeGICombiner.inc"135#undef GET_GICOMBINER_CONSTRUCTOR_INITS136{137}138 139class RISCVPostLegalizerCombiner : public MachineFunctionPass {140public:141 static char ID;142 143 RISCVPostLegalizerCombiner();144 145 StringRef getPassName() const override {146 return "RISCVPostLegalizerCombiner";147 }148 149 bool runOnMachineFunction(MachineFunction &MF) override;150 void getAnalysisUsage(AnalysisUsage &AU) const override;151 152private:153 RISCVPostLegalizerCombinerImplRuleConfig RuleConfig;154};155} // end anonymous namespace156 157void RISCVPostLegalizerCombiner::getAnalysisUsage(AnalysisUsage &AU) const {158 AU.addRequired<TargetPassConfig>();159 AU.setPreservesCFG();160 getSelectionDAGFallbackAnalysisUsage(AU);161 AU.addRequired<GISelValueTrackingAnalysisLegacy>();162 AU.addPreserved<GISelValueTrackingAnalysisLegacy>();163 AU.addRequired<MachineDominatorTreeWrapperPass>();164 AU.addPreserved<MachineDominatorTreeWrapperPass>();165 AU.addRequired<GISelCSEAnalysisWrapperPass>();166 AU.addPreserved<GISelCSEAnalysisWrapperPass>();167 MachineFunctionPass::getAnalysisUsage(AU);168}169 170RISCVPostLegalizerCombiner::RISCVPostLegalizerCombiner()171 : MachineFunctionPass(ID) {172 if (!RuleConfig.parseCommandLineOption())173 report_fatal_error("Invalid rule identifier");174}175 176bool RISCVPostLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) {177 if (MF.getProperties().hasFailedISel())178 return false;179 assert(MF.getProperties().hasLegalized() && "Expected a legalized function?");180 auto *TPC = &getAnalysis<TargetPassConfig>();181 const Function &F = MF.getFunction();182 bool EnableOpt =183 MF.getTarget().getOptLevel() != CodeGenOptLevel::None && !skipFunction(F);184 185 const RISCVSubtarget &ST = MF.getSubtarget<RISCVSubtarget>();186 const auto *LI = ST.getLegalizerInfo();187 188 GISelValueTracking *VT =189 &getAnalysis<GISelValueTrackingAnalysisLegacy>().get(MF);190 MachineDominatorTree *MDT =191 &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();192 GISelCSEAnalysisWrapper &Wrapper =193 getAnalysis<GISelCSEAnalysisWrapperPass>().getCSEWrapper();194 auto *CSEInfo = &Wrapper.get(TPC->getCSEConfig());195 196 CombinerInfo CInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false,197 /*LegalizerInfo*/ nullptr, EnableOpt, F.hasOptSize(),198 F.hasMinSize());199 RISCVPostLegalizerCombinerImpl Impl(MF, CInfo, TPC, *VT, CSEInfo, RuleConfig,200 ST, MDT, LI);201 return Impl.combineMachineInstrs();202}203 204char RISCVPostLegalizerCombiner::ID = 0;205INITIALIZE_PASS_BEGIN(RISCVPostLegalizerCombiner, DEBUG_TYPE,206 "Combine RISC-V MachineInstrs after legalization", false,207 false)208INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)209INITIALIZE_PASS_DEPENDENCY(GISelValueTrackingAnalysisLegacy)210INITIALIZE_PASS_END(RISCVPostLegalizerCombiner, DEBUG_TYPE,211 "Combine RISC-V MachineInstrs after legalization", false,212 false)213 214FunctionPass *llvm::createRISCVPostLegalizerCombiner() {215 return new RISCVPostLegalizerCombiner();216}217