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