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
27using namespace llvm;
28
29namespace {
30struct MipsPreLegalizerCombinerInfo : public CombinerInfo {
31public:
32 MipsPreLegalizerCombinerInfo()
33 : CombinerInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false,
34 /*LegalizerInfo*/ nullptr, /*EnableOpt*/ false,
35 /*EnableOptSize*/ false, /*EnableMinSize*/ false) {}
36};
37
38class MipsPreLegalizerCombinerImpl : public Combiner {
39protected:
40 const MipsSubtarget &STI;
41 // TODO: Make CombinerHelper methods const.
42 mutable CombinerHelper Helper;
43
44public:
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 (!MMO->getSize().hasValue() ||
74 !isPowerOf2_64(Value: MMO->getSize().getValue()))
75 return false;
76 bool isUnaligned = MMO->getAlign() < MMO->getSize().getValue();
77 if (!STI.systemSupportsUnalignedAccess() && isUnaligned)
78 return false;
79
80 return Helper.tryCombineExtendingLoads(MI);
81 }
82 }
83
84 return false;
85 }
86};
87
88// Pass boilerplate
89// ================
90
91class MipsPreLegalizerCombiner : public MachineFunctionPass {
92public:
93 static char ID;
94
95 MipsPreLegalizerCombiner();
96
97 StringRef getPassName() const override { return "MipsPreLegalizerCombiner"; }
98
99 bool runOnMachineFunction(MachineFunction &MF) override;
100
101 void getAnalysisUsage(AnalysisUsage &AU) const override;
102};
103} // end anonymous namespace
104
105void MipsPreLegalizerCombiner::getAnalysisUsage(AnalysisUsage &AU) const {
106 AU.addRequired<TargetPassConfig>();
107 AU.addRequired<GISelKnownBitsAnalysis>();
108 AU.addPreserved<GISelKnownBitsAnalysis>();
109 AU.setPreservesCFG();
110 getSelectionDAGFallbackAnalysisUsage(AU);
111 MachineFunctionPass::getAnalysisUsage(AU);
112}
113
114MipsPreLegalizerCombiner::MipsPreLegalizerCombiner() : MachineFunctionPass(ID) {
115 initializeMipsPreLegalizerCombinerPass(*PassRegistry::getPassRegistry());
116}
117
118bool MipsPreLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) {
119 if (MF.getProperties().hasProperty(
120 P: MachineFunctionProperties::Property::FailedISel))
121 return false;
122
123 auto *TPC = &getAnalysis<TargetPassConfig>();
124 const MipsSubtarget &ST = MF.getSubtarget<MipsSubtarget>();
125 const MipsLegalizerInfo *LI =
126 static_cast<const MipsLegalizerInfo *>(ST.getLegalizerInfo());
127
128 GISelKnownBits *KB = &getAnalysis<GISelKnownBitsAnalysis>().get(MF);
129 MipsPreLegalizerCombinerInfo PCInfo;
130 MipsPreLegalizerCombinerImpl Impl(MF, PCInfo, TPC, *KB, /*CSEInfo*/ nullptr,
131 ST, /*MDT*/ nullptr, LI);
132 return Impl.combineMachineInstrs();
133}
134
135char MipsPreLegalizerCombiner::ID = 0;
136INITIALIZE_PASS_BEGIN(MipsPreLegalizerCombiner, DEBUG_TYPE,
137 "Combine Mips machine instrs before legalization", false,
138 false)
139INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
140INITIALIZE_PASS_DEPENDENCY(GISelKnownBitsAnalysis)
141INITIALIZE_PASS_END(MipsPreLegalizerCombiner, DEBUG_TYPE,
142 "Combine Mips machine instrs before legalization", false,
143 false)
144
145namespace llvm {
146FunctionPass *createMipsPreLegalizeCombiner() {
147 return new MipsPreLegalizerCombiner();
148}
149} // end namespace llvm
150