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