10b57cec5SDimitry Andric //=== lib/CodeGen/GlobalISel/MipsPreLegalizerCombiner.cpp --------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This pass does combining of machine instructions at the generic MI level,
100b57cec5SDimitry Andric // before the legalizer.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric
145f757f3fSDimitry Andric #include "MipsLegalizerInfo.h"
150b57cec5SDimitry Andric #include "MipsTargetMachine.h"
160b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/Combiner.h"
170b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/CombinerHelper.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/CombinerInfo.h"
195f757f3fSDimitry Andric #include "llvm/CodeGen/GlobalISel/GISelKnownBits.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
2181ad6265SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h"
23480093f4SDimitry Andric #include "llvm/InitializePasses.h"
240b57cec5SDimitry Andric
250b57cec5SDimitry Andric #define DEBUG_TYPE "mips-prelegalizer-combiner"
260b57cec5SDimitry Andric
270b57cec5SDimitry Andric using namespace llvm;
280b57cec5SDimitry Andric
290b57cec5SDimitry Andric namespace {
305f757f3fSDimitry Andric struct MipsPreLegalizerCombinerInfo : public CombinerInfo {
310b57cec5SDimitry Andric public:
MipsPreLegalizerCombinerInfo__anonb65b3b5c0111::MipsPreLegalizerCombinerInfo320b57cec5SDimitry Andric MipsPreLegalizerCombinerInfo()
330b57cec5SDimitry Andric : CombinerInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false,
348bcb0991SDimitry Andric /*LegalizerInfo*/ nullptr, /*EnableOpt*/ false,
358bcb0991SDimitry Andric /*EnableOptSize*/ false, /*EnableMinSize*/ false) {}
360b57cec5SDimitry Andric };
370b57cec5SDimitry Andric
385f757f3fSDimitry Andric class MipsPreLegalizerCombinerImpl : public Combiner {
395f757f3fSDimitry Andric protected:
405f757f3fSDimitry Andric const MipsSubtarget &STI;
415f757f3fSDimitry Andric // TODO: Make CombinerHelper methods const.
425f757f3fSDimitry Andric mutable CombinerHelper Helper;
435f757f3fSDimitry Andric
445f757f3fSDimitry Andric public:
MipsPreLegalizerCombinerImpl(MachineFunction & MF,CombinerInfo & CInfo,const TargetPassConfig * TPC,GISelKnownBits & KB,GISelCSEInfo * CSEInfo,const MipsSubtarget & STI,MachineDominatorTree * MDT,const LegalizerInfo * LI)455f757f3fSDimitry Andric MipsPreLegalizerCombinerImpl(MachineFunction &MF, CombinerInfo &CInfo,
465f757f3fSDimitry Andric const TargetPassConfig *TPC, GISelKnownBits &KB,
475f757f3fSDimitry Andric GISelCSEInfo *CSEInfo, const MipsSubtarget &STI,
485f757f3fSDimitry Andric MachineDominatorTree *MDT,
495f757f3fSDimitry Andric const LegalizerInfo *LI)
505f757f3fSDimitry Andric : Combiner(MF, CInfo, TPC, &KB, CSEInfo), STI(STI),
515f757f3fSDimitry Andric Helper(Observer, B, /*IsPreLegalize*/ true, &KB, MDT, LI) {}
525f757f3fSDimitry Andric
getName()535f757f3fSDimitry Andric static const char *getName() { return "MipsPreLegalizerCombiner"; }
545f757f3fSDimitry Andric
setupGeneratedPerFunctionState(MachineFunction & MF)555f757f3fSDimitry Andric void setupGeneratedPerFunctionState(MachineFunction &MF) override {
565f757f3fSDimitry Andric // TODO: TableGen-erate this class' impl.
575f757f3fSDimitry Andric }
585f757f3fSDimitry Andric
tryCombineAll(MachineInstr & MI) const595f757f3fSDimitry Andric bool tryCombineAll(MachineInstr &MI) const override {
600b57cec5SDimitry Andric
610b57cec5SDimitry Andric switch (MI.getOpcode()) {
620b57cec5SDimitry Andric default:
630b57cec5SDimitry Andric return false;
64fe6060f1SDimitry Andric case TargetOpcode::G_MEMCPY_INLINE:
65fe6060f1SDimitry Andric return Helper.tryEmitMemcpyInline(MI);
660b57cec5SDimitry Andric case TargetOpcode::G_LOAD:
670b57cec5SDimitry Andric case TargetOpcode::G_SEXTLOAD:
685ffd83dbSDimitry Andric case TargetOpcode::G_ZEXTLOAD: {
695ffd83dbSDimitry Andric // Don't attempt to combine non power of 2 loads or unaligned loads when
705ffd83dbSDimitry Andric // subtarget doesn't support them.
715ffd83dbSDimitry Andric auto MMO = *MI.memoperands_begin();
7281ad6265SDimitry Andric const MipsSubtarget &STI = MI.getMF()->getSubtarget<MipsSubtarget>();
73*0fca6ea1SDimitry Andric if (!MMO->getSize().hasValue() ||
74*0fca6ea1SDimitry Andric !isPowerOf2_64(MMO->getSize().getValue()))
755ffd83dbSDimitry Andric return false;
76*0fca6ea1SDimitry Andric bool isUnaligned = MMO->getAlign() < MMO->getSize().getValue();
775ffd83dbSDimitry Andric if (!STI.systemSupportsUnalignedAccess() && isUnaligned)
785ffd83dbSDimitry Andric return false;
795ffd83dbSDimitry Andric
800b57cec5SDimitry Andric return Helper.tryCombineExtendingLoads(MI);
810b57cec5SDimitry Andric }
825ffd83dbSDimitry Andric }
835ffd83dbSDimitry Andric
840b57cec5SDimitry Andric return false;
850b57cec5SDimitry Andric }
865f757f3fSDimitry Andric };
870b57cec5SDimitry Andric
880b57cec5SDimitry Andric // Pass boilerplate
890b57cec5SDimitry Andric // ================
900b57cec5SDimitry Andric
910b57cec5SDimitry Andric class MipsPreLegalizerCombiner : public MachineFunctionPass {
920b57cec5SDimitry Andric public:
930b57cec5SDimitry Andric static char ID;
940b57cec5SDimitry Andric
950b57cec5SDimitry Andric MipsPreLegalizerCombiner();
960b57cec5SDimitry Andric
getPassName() const970b57cec5SDimitry Andric StringRef getPassName() const override { return "MipsPreLegalizerCombiner"; }
980b57cec5SDimitry Andric
990b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override;
1000b57cec5SDimitry Andric
1010b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override;
1020b57cec5SDimitry Andric };
1030b57cec5SDimitry Andric } // end anonymous namespace
1040b57cec5SDimitry Andric
getAnalysisUsage(AnalysisUsage & AU) const1050b57cec5SDimitry Andric void MipsPreLegalizerCombiner::getAnalysisUsage(AnalysisUsage &AU) const {
1060b57cec5SDimitry Andric AU.addRequired<TargetPassConfig>();
1075f757f3fSDimitry Andric AU.addRequired<GISelKnownBitsAnalysis>();
1085f757f3fSDimitry Andric AU.addPreserved<GISelKnownBitsAnalysis>();
1090b57cec5SDimitry Andric AU.setPreservesCFG();
1100b57cec5SDimitry Andric getSelectionDAGFallbackAnalysisUsage(AU);
1110b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU);
1120b57cec5SDimitry Andric }
1130b57cec5SDimitry Andric
MipsPreLegalizerCombiner()1140b57cec5SDimitry Andric MipsPreLegalizerCombiner::MipsPreLegalizerCombiner() : MachineFunctionPass(ID) {
1150b57cec5SDimitry Andric initializeMipsPreLegalizerCombinerPass(*PassRegistry::getPassRegistry());
1160b57cec5SDimitry Andric }
1170b57cec5SDimitry Andric
runOnMachineFunction(MachineFunction & MF)1180b57cec5SDimitry Andric bool MipsPreLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) {
1190b57cec5SDimitry Andric if (MF.getProperties().hasProperty(
1200b57cec5SDimitry Andric MachineFunctionProperties::Property::FailedISel))
1210b57cec5SDimitry Andric return false;
1225f757f3fSDimitry Andric
1230b57cec5SDimitry Andric auto *TPC = &getAnalysis<TargetPassConfig>();
1245f757f3fSDimitry Andric const MipsSubtarget &ST = MF.getSubtarget<MipsSubtarget>();
1255f757f3fSDimitry Andric const MipsLegalizerInfo *LI =
1265f757f3fSDimitry Andric static_cast<const MipsLegalizerInfo *>(ST.getLegalizerInfo());
1275f757f3fSDimitry Andric
1285f757f3fSDimitry Andric GISelKnownBits *KB = &getAnalysis<GISelKnownBitsAnalysis>().get(MF);
1290b57cec5SDimitry Andric MipsPreLegalizerCombinerInfo PCInfo;
1305f757f3fSDimitry Andric MipsPreLegalizerCombinerImpl Impl(MF, PCInfo, TPC, *KB, /*CSEInfo*/ nullptr,
1315f757f3fSDimitry Andric ST, /*MDT*/ nullptr, LI);
1325f757f3fSDimitry Andric return Impl.combineMachineInstrs();
1330b57cec5SDimitry Andric }
1340b57cec5SDimitry Andric
1350b57cec5SDimitry Andric char MipsPreLegalizerCombiner::ID = 0;
1360b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(MipsPreLegalizerCombiner, DEBUG_TYPE,
1370b57cec5SDimitry Andric "Combine Mips machine instrs before legalization", false,
1380b57cec5SDimitry Andric false)
1390b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
1405f757f3fSDimitry Andric INITIALIZE_PASS_DEPENDENCY(GISelKnownBitsAnalysis)
1410b57cec5SDimitry Andric INITIALIZE_PASS_END(MipsPreLegalizerCombiner, DEBUG_TYPE,
1420b57cec5SDimitry Andric "Combine Mips machine instrs before legalization", false,
1430b57cec5SDimitry Andric false)
1440b57cec5SDimitry Andric
1450b57cec5SDimitry Andric namespace llvm {
createMipsPreLegalizeCombiner()1460b57cec5SDimitry Andric FunctionPass *createMipsPreLegalizeCombiner() {
1470b57cec5SDimitry Andric return new MipsPreLegalizerCombiner();
1480b57cec5SDimitry Andric }
1490b57cec5SDimitry Andric } // end namespace llvm
150