1 //=== lib/CodeGen/GlobalISel/MipsPostLegalizerCombiner.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 // after the legalizer.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "MCTargetDesc/MipsMCTargetDesc.h"
15 #include "Mips.h"
16 #include "MipsLegalizerInfo.h"
17 #include "MipsSubtarget.h"
18 #include "llvm/CodeGen/GlobalISel/Combiner.h"
19 #include "llvm/CodeGen/GlobalISel/CombinerHelper.h"
20 #include "llvm/CodeGen/GlobalISel/CombinerInfo.h"
21 #include "llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h"
22 #include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"
23 #include "llvm/CodeGen/GlobalISel/GISelKnownBits.h"
24 #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
25 #include "llvm/CodeGen/MachineDominators.h"
26 #include "llvm/CodeGen/TargetPassConfig.h"
27 #include "llvm/Target/TargetMachine.h"
28 
29 #define GET_GICOMBINER_DEPS
30 #include "MipsGenPostLegalizeGICombiner.inc"
31 #undef GET_GICOMBINER_DEPS
32 
33 #define DEBUG_TYPE "mips-postlegalizer-combiner"
34 
35 using namespace llvm;
36 using namespace MIPatternMatch;
37 
38 namespace {
39 #define GET_GICOMBINER_TYPES
40 #include "MipsGenPostLegalizeGICombiner.inc"
41 #undef GET_GICOMBINER_TYPES
42 
43 class MipsPostLegalizerCombinerImpl : public GIMatchTableExecutor {
44 protected:
45   CombinerHelper &Helper;
46   const MipsPostLegalizerCombinerImplRuleConfig &RuleConfig;
47 
48   const MipsSubtarget &STI;
49   GISelChangeObserver &Observer;
50   MachineIRBuilder &B;
51   MachineFunction &MF;
52 
53   MachineRegisterInfo &MRI;
54 
55 public:
56   MipsPostLegalizerCombinerImpl(
57       const MipsPostLegalizerCombinerImplRuleConfig &RuleConfig,
58       const MipsSubtarget &STI, GISelChangeObserver &Observer,
59       MachineIRBuilder &B, CombinerHelper &Helper);
60 
61   static const char *getName() { return "MipsPostLegalizerCombiner"; }
62 
63   bool tryCombineAll(MachineInstr &I) const;
64 
65 private:
66 #define GET_GICOMBINER_CLASS_MEMBERS
67 #include "MipsGenPostLegalizeGICombiner.inc"
68 #undef GET_GICOMBINER_CLASS_MEMBERS
69 };
70 
71 #define GET_GICOMBINER_IMPL
72 #include "MipsGenPostLegalizeGICombiner.inc"
73 #undef GET_GICOMBINER_IMPL
74 
75 MipsPostLegalizerCombinerImpl::MipsPostLegalizerCombinerImpl(
76     const MipsPostLegalizerCombinerImplRuleConfig &RuleConfig,
77     const MipsSubtarget &STI, GISelChangeObserver &Observer,
78     MachineIRBuilder &B, CombinerHelper &Helper)
79     : Helper(Helper), RuleConfig(RuleConfig), STI(STI), Observer(Observer),
80       B(B), MF(B.getMF()), MRI(*B.getMRI()),
81 #define GET_GICOMBINER_CONSTRUCTOR_INITS
82 #include "MipsGenPostLegalizeGICombiner.inc"
83 #undef GET_GICOMBINER_CONSTRUCTOR_INITS
84 {
85 }
86 
87 class MipsPostLegalizerCombinerInfo final : public CombinerInfo {
88   GISelKnownBits *KB;
89 
90 public:
91   MipsPostLegalizerCombinerImplRuleConfig RuleConfig;
92 
93   MipsPostLegalizerCombinerInfo(bool EnableOpt, bool OptSize, bool MinSize,
94                                 GISelKnownBits *KB, const MipsLegalizerInfo *LI)
95       : CombinerInfo(/*AllowIllegalOps*/ false, /*ShouldLegalizeIllegal*/ true,
96                      /*LegalizerInfo*/ LI, EnableOpt, OptSize, MinSize),
97         KB(KB) {
98     if (!RuleConfig.parseCommandLineOption())
99       report_fatal_error("Invalid rule identifier");
100   }
101 
102   bool combine(GISelChangeObserver &Observer, MachineInstr &MI,
103                MachineIRBuilder &B) const override;
104 };
105 
106 bool MipsPostLegalizerCombinerInfo::combine(GISelChangeObserver &Observer,
107                                             MachineInstr &MI,
108                                             MachineIRBuilder &B) const {
109   const auto &STI = MI.getMF()->getSubtarget<MipsSubtarget>();
110   CombinerHelper Helper(Observer, B, /* IsPreLegalize*/ false, KB,
111                         /*DominatorTree*/ nullptr, LInfo);
112   MipsPostLegalizerCombinerImpl Impl(RuleConfig, STI, Observer, B, Helper);
113   Impl.setupMF(*MI.getMF(), KB);
114   return Impl.tryCombineAll(MI);
115 }
116 
117 // Pass boilerplate
118 // ================
119 
120 class MipsPostLegalizerCombiner : public MachineFunctionPass {
121 public:
122   static char ID;
123 
124   MipsPostLegalizerCombiner(bool IsOptNone = false);
125 
126   StringRef getPassName() const override {
127     return "MipsPostLegalizerCombiner";
128   }
129 
130   bool runOnMachineFunction(MachineFunction &MF) override;
131 
132   void getAnalysisUsage(AnalysisUsage &AU) const override;
133 
134 private:
135   bool IsOptNone;
136 };
137 } // end anonymous namespace
138 
139 void MipsPostLegalizerCombiner::getAnalysisUsage(AnalysisUsage &AU) const {
140   AU.addRequired<TargetPassConfig>();
141   AU.setPreservesCFG();
142   getSelectionDAGFallbackAnalysisUsage(AU);
143   AU.addRequired<GISelKnownBitsAnalysis>();
144   AU.addPreserved<GISelKnownBitsAnalysis>();
145   if (!IsOptNone) {
146     AU.addRequired<MachineDominatorTree>();
147     AU.addPreserved<MachineDominatorTree>();
148   }
149   MachineFunctionPass::getAnalysisUsage(AU);
150 }
151 
152 MipsPostLegalizerCombiner::MipsPostLegalizerCombiner(bool IsOptNone)
153     : MachineFunctionPass(ID), IsOptNone(IsOptNone) {
154   initializeMipsPostLegalizerCombinerPass(*PassRegistry::getPassRegistry());
155 }
156 
157 bool MipsPostLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) {
158   if (MF.getProperties().hasProperty(
159           MachineFunctionProperties::Property::FailedISel))
160     return false;
161   auto *TPC = &getAnalysis<TargetPassConfig>();
162   const Function &F = MF.getFunction();
163   bool EnableOpt =
164       MF.getTarget().getOptLevel() != CodeGenOpt::None && !skipFunction(F);
165 
166   const MipsSubtarget &ST = MF.getSubtarget<MipsSubtarget>();
167   const MipsLegalizerInfo *LI =
168       static_cast<const MipsLegalizerInfo *>(ST.getLegalizerInfo());
169 
170   GISelKnownBits *KB = &getAnalysis<GISelKnownBitsAnalysis>().get(MF);
171   MipsPostLegalizerCombinerInfo PCInfo(EnableOpt, F.hasOptSize(),
172                                        F.hasMinSize(), KB, LI);
173   Combiner C(PCInfo, TPC);
174   return C.combineMachineInstrs(MF, /*CSEInfo*/ nullptr);
175 }
176 
177 char MipsPostLegalizerCombiner::ID = 0;
178 INITIALIZE_PASS_BEGIN(MipsPostLegalizerCombiner, DEBUG_TYPE,
179                       "Combine Mips machine instrs after legalization", false,
180                       false)
181 INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
182 INITIALIZE_PASS_DEPENDENCY(GISelKnownBitsAnalysis)
183 INITIALIZE_PASS_END(MipsPostLegalizerCombiner, DEBUG_TYPE,
184                     "Combine Mips machine instrs after legalization", false,
185                     false)
186 
187 namespace llvm {
188 FunctionPass *createMipsPostLegalizeCombiner(bool IsOptNone) {
189   return new MipsPostLegalizerCombiner(IsOptNone);
190 }
191 } // end namespace llvm
192