1//=== RISCVO0PreLegalizerCombiner.cpp -------------------------------------===//
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-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This pass does combining of machine instructions at the generic MI level,
10// before the legalizer.
11//
12//===----------------------------------------------------------------------===//
13
14#include "RISCVSubtarget.h"
15#include "llvm/CodeGen/GlobalISel/Combiner.h"
16#include "llvm/CodeGen/GlobalISel/CombinerHelper.h"
17#include "llvm/CodeGen/GlobalISel/CombinerInfo.h"
18#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"
19#include "llvm/CodeGen/GlobalISel/GISelKnownBits.h"
20#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
21#include "llvm/CodeGen/MachineDominators.h"
22#include "llvm/CodeGen/MachineFunction.h"
23#include "llvm/CodeGen/MachineFunctionPass.h"
24#include "llvm/CodeGen/MachineRegisterInfo.h"
25#include "llvm/CodeGen/TargetPassConfig.h"
26
27#define GET_GICOMBINER_DEPS
28#include "RISCVGenO0PreLegalizeGICombiner.inc"
29#undef GET_GICOMBINER_DEPS
30
31#define DEBUG_TYPE "riscv-O0-prelegalizer-combiner"
32
33using namespace llvm;
34
35namespace {
36#define GET_GICOMBINER_TYPES
37#include "RISCVGenO0PreLegalizeGICombiner.inc"
38#undef GET_GICOMBINER_TYPES
39
40class RISCVO0PreLegalizerCombinerImpl : public Combiner {
41protected:
42  // TODO: Make CombinerHelper methods const.
43  mutable CombinerHelper Helper;
44  const RISCVO0PreLegalizerCombinerImplRuleConfig &RuleConfig;
45  const RISCVSubtarget &STI;
46
47public:
48  RISCVO0PreLegalizerCombinerImpl(
49      MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC,
50      GISelKnownBits &KB, GISelCSEInfo *CSEInfo,
51      const RISCVO0PreLegalizerCombinerImplRuleConfig &RuleConfig,
52      const RISCVSubtarget &STI);
53
54  static const char *getName() { return "RISCVO0PreLegalizerCombiner"; }
55
56  bool tryCombineAll(MachineInstr &I) const override;
57
58private:
59#define GET_GICOMBINER_CLASS_MEMBERS
60#include "RISCVGenO0PreLegalizeGICombiner.inc"
61#undef GET_GICOMBINER_CLASS_MEMBERS
62};
63
64#define GET_GICOMBINER_IMPL
65#include "RISCVGenO0PreLegalizeGICombiner.inc"
66#undef GET_GICOMBINER_IMPL
67
68RISCVO0PreLegalizerCombinerImpl::RISCVO0PreLegalizerCombinerImpl(
69    MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC,
70    GISelKnownBits &KB, GISelCSEInfo *CSEInfo,
71    const RISCVO0PreLegalizerCombinerImplRuleConfig &RuleConfig,
72    const RISCVSubtarget &STI)
73    : Combiner(MF, CInfo, TPC, &KB, CSEInfo),
74      Helper(Observer, B, /*IsPreLegalize*/ true, &KB), RuleConfig(RuleConfig),
75      STI(STI),
76#define GET_GICOMBINER_CONSTRUCTOR_INITS
77#include "RISCVGenO0PreLegalizeGICombiner.inc"
78#undef GET_GICOMBINER_CONSTRUCTOR_INITS
79{
80}
81
82// Pass boilerplate
83// ================
84
85class RISCVO0PreLegalizerCombiner : public MachineFunctionPass {
86public:
87  static char ID;
88
89  RISCVO0PreLegalizerCombiner();
90
91  StringRef getPassName() const override {
92    return "RISCVO0PreLegalizerCombiner";
93  }
94
95  bool runOnMachineFunction(MachineFunction &MF) override;
96
97  void getAnalysisUsage(AnalysisUsage &AU) const override;
98
99private:
100  RISCVO0PreLegalizerCombinerImplRuleConfig RuleConfig;
101};
102} // end anonymous namespace
103
104void RISCVO0PreLegalizerCombiner::getAnalysisUsage(AnalysisUsage &AU) const {
105  AU.addRequired<TargetPassConfig>();
106  AU.setPreservesCFG();
107  getSelectionDAGFallbackAnalysisUsage(AU);
108  AU.addRequired<GISelKnownBitsAnalysis>();
109  AU.addPreserved<GISelKnownBitsAnalysis>();
110  MachineFunctionPass::getAnalysisUsage(AU);
111}
112
113RISCVO0PreLegalizerCombiner::RISCVO0PreLegalizerCombiner()
114    : MachineFunctionPass(ID) {
115  initializeRISCVO0PreLegalizerCombinerPass(*PassRegistry::getPassRegistry());
116
117  if (!RuleConfig.parseCommandLineOption())
118    report_fatal_error("Invalid rule identifier");
119}
120
121bool RISCVO0PreLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) {
122  if (MF.getProperties().hasProperty(
123          MachineFunctionProperties::Property::FailedISel))
124    return false;
125  auto &TPC = getAnalysis<TargetPassConfig>();
126
127  const Function &F = MF.getFunction();
128  GISelKnownBits *KB = &getAnalysis<GISelKnownBitsAnalysis>().get(MF);
129
130  const RISCVSubtarget &ST = MF.getSubtarget<RISCVSubtarget>();
131
132  CombinerInfo CInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false,
133                     /*LegalizerInfo*/ nullptr, /*EnableOpt*/ false,
134                     F.hasOptSize(), F.hasMinSize());
135  RISCVO0PreLegalizerCombinerImpl Impl(MF, CInfo, &TPC, *KB,
136                                       /*CSEInfo*/ nullptr, RuleConfig, ST);
137  return Impl.combineMachineInstrs();
138}
139
140char RISCVO0PreLegalizerCombiner::ID = 0;
141INITIALIZE_PASS_BEGIN(RISCVO0PreLegalizerCombiner, DEBUG_TYPE,
142                      "Combine RISC-V machine instrs before legalization", false,
143                      false)
144INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
145INITIALIZE_PASS_DEPENDENCY(GISelKnownBitsAnalysis)
146INITIALIZE_PASS_DEPENDENCY(GISelCSEAnalysisWrapperPass)
147INITIALIZE_PASS_END(RISCVO0PreLegalizerCombiner, DEBUG_TYPE,
148                    "Combine RISC-V machine instrs before legalization", false,
149                    false)
150
151namespace llvm {
152FunctionPass *createRISCVO0PreLegalizerCombiner() {
153  return new RISCVO0PreLegalizerCombiner();
154}
155} // end namespace llvm
156