1 //=== lib/CodeGen/GlobalISel/MipsPreLegalizerCombiner.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 "MipsLegalizerInfo.h"
15 #include "MipsTargetMachine.h"
16 #include "llvm/CodeGen/GlobalISel/Combiner.h"
17 #include "llvm/CodeGen/GlobalISel/CombinerHelper.h"
18 #include "llvm/CodeGen/GlobalISel/CombinerInfo.h"
19 #include "llvm/CodeGen/GlobalISel/GISelKnownBits.h"
20 #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
21 #include "llvm/CodeGen/MachineFunctionPass.h"
22 #include "llvm/CodeGen/TargetPassConfig.h"
23 #include "llvm/InitializePasses.h"
24 
25 #define DEBUG_TYPE "mips-prelegalizer-combiner"
26 
27 using namespace llvm;
28 
29 namespace {
30 struct MipsPreLegalizerCombinerInfo : public CombinerInfo {
31 public:
32   MipsPreLegalizerCombinerInfo()
33       : CombinerInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false,
34                      /*LegalizerInfo*/ nullptr, /*EnableOpt*/ false,
35                      /*EnableOptSize*/ false, /*EnableMinSize*/ false) {}
36 };
37 
38 class MipsPreLegalizerCombinerImpl : public Combiner {
39 protected:
40   const MipsSubtarget &STI;
41   // TODO: Make CombinerHelper methods const.
42   mutable CombinerHelper Helper;
43 
44 public:
45   MipsPreLegalizerCombinerImpl(MachineFunction &MF, CombinerInfo &CInfo,
46                                const TargetPassConfig *TPC, GISelKnownBits &KB,
47                                GISelCSEInfo *CSEInfo, const MipsSubtarget &STI,
48                                MachineDominatorTree *MDT,
49                                const LegalizerInfo *LI)
50       : Combiner(MF, CInfo, TPC, &KB, CSEInfo), STI(STI),
51         Helper(Observer, B, /*IsPreLegalize*/ true, &KB, MDT, LI) {}
52 
53   static const char *getName() { return "MipsPreLegalizerCombiner"; }
54 
55   void setupGeneratedPerFunctionState(MachineFunction &MF) override {
56     // TODO: TableGen-erate this class' impl.
57   }
58 
59   bool tryCombineAll(MachineInstr &MI) const override {
60 
61     switch (MI.getOpcode()) {
62     default:
63       return false;
64     case TargetOpcode::G_MEMCPY_INLINE:
65       return Helper.tryEmitMemcpyInline(MI);
66     case TargetOpcode::G_LOAD:
67     case TargetOpcode::G_SEXTLOAD:
68     case TargetOpcode::G_ZEXTLOAD: {
69       // Don't attempt to combine non power of 2 loads or unaligned loads when
70       // subtarget doesn't support them.
71       auto MMO = *MI.memoperands_begin();
72       const MipsSubtarget &STI = MI.getMF()->getSubtarget<MipsSubtarget>();
73       if (!isPowerOf2_64(MMO->getSize()))
74         return false;
75       bool isUnaligned = MMO->getAlign() < MMO->getSize();
76       if (!STI.systemSupportsUnalignedAccess() && isUnaligned)
77         return false;
78 
79       return Helper.tryCombineExtendingLoads(MI);
80     }
81     }
82 
83     return false;
84   }
85 };
86 
87 // Pass boilerplate
88 // ================
89 
90 class MipsPreLegalizerCombiner : public MachineFunctionPass {
91 public:
92   static char ID;
93 
94   MipsPreLegalizerCombiner();
95 
96   StringRef getPassName() const override { return "MipsPreLegalizerCombiner"; }
97 
98   bool runOnMachineFunction(MachineFunction &MF) override;
99 
100   void getAnalysisUsage(AnalysisUsage &AU) const override;
101 };
102 } // end anonymous namespace
103 
104 void MipsPreLegalizerCombiner::getAnalysisUsage(AnalysisUsage &AU) const {
105   AU.addRequired<TargetPassConfig>();
106   AU.addRequired<GISelKnownBitsAnalysis>();
107   AU.addPreserved<GISelKnownBitsAnalysis>();
108   AU.setPreservesCFG();
109   getSelectionDAGFallbackAnalysisUsage(AU);
110   MachineFunctionPass::getAnalysisUsage(AU);
111 }
112 
113 MipsPreLegalizerCombiner::MipsPreLegalizerCombiner() : MachineFunctionPass(ID) {
114   initializeMipsPreLegalizerCombinerPass(*PassRegistry::getPassRegistry());
115 }
116 
117 bool MipsPreLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) {
118   if (MF.getProperties().hasProperty(
119           MachineFunctionProperties::Property::FailedISel))
120     return false;
121 
122   auto *TPC = &getAnalysis<TargetPassConfig>();
123   const MipsSubtarget &ST = MF.getSubtarget<MipsSubtarget>();
124   const MipsLegalizerInfo *LI =
125       static_cast<const MipsLegalizerInfo *>(ST.getLegalizerInfo());
126 
127   GISelKnownBits *KB = &getAnalysis<GISelKnownBitsAnalysis>().get(MF);
128   MipsPreLegalizerCombinerInfo PCInfo;
129   MipsPreLegalizerCombinerImpl Impl(MF, PCInfo, TPC, *KB, /*CSEInfo*/ nullptr,
130                                     ST, /*MDT*/ nullptr, LI);
131   return Impl.combineMachineInstrs();
132 }
133 
134 char MipsPreLegalizerCombiner::ID = 0;
135 INITIALIZE_PASS_BEGIN(MipsPreLegalizerCombiner, DEBUG_TYPE,
136                       "Combine Mips machine instrs before legalization", false,
137                       false)
138 INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
139 INITIALIZE_PASS_DEPENDENCY(GISelKnownBitsAnalysis)
140 INITIALIZE_PASS_END(MipsPreLegalizerCombiner, DEBUG_TYPE,
141                     "Combine Mips machine instrs before legalization", false,
142                     false)
143 
144 namespace llvm {
145 FunctionPass *createMipsPreLegalizeCombiner() {
146   return new MipsPreLegalizerCombiner();
147 }
148 } // end namespace llvm
149