xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Mips/MipsPreLegalizerCombiner.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
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 
140b57cec5SDimitry Andric #include "MipsTargetMachine.h"
150b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/Combiner.h"
160b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/CombinerHelper.h"
170b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/CombinerInfo.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h"
20480093f4SDimitry Andric #include "llvm/InitializePasses.h"
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric #define DEBUG_TYPE "mips-prelegalizer-combiner"
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric using namespace llvm;
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric namespace {
270b57cec5SDimitry Andric class MipsPreLegalizerCombinerInfo : public CombinerInfo {
280b57cec5SDimitry Andric public:
290b57cec5SDimitry Andric   MipsPreLegalizerCombinerInfo()
300b57cec5SDimitry Andric       : CombinerInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false,
318bcb0991SDimitry Andric                      /*LegalizerInfo*/ nullptr, /*EnableOpt*/ false,
328bcb0991SDimitry Andric                      /*EnableOptSize*/ false, /*EnableMinSize*/ false) {}
330b57cec5SDimitry Andric   virtual bool combine(GISelChangeObserver &Observer, MachineInstr &MI,
340b57cec5SDimitry Andric                        MachineIRBuilder &B) const override;
350b57cec5SDimitry Andric };
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric bool MipsPreLegalizerCombinerInfo::combine(GISelChangeObserver &Observer,
380b57cec5SDimitry Andric                                            MachineInstr &MI,
390b57cec5SDimitry Andric                                            MachineIRBuilder &B) const {
400b57cec5SDimitry Andric   CombinerHelper Helper(Observer, B);
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric   switch (MI.getOpcode()) {
430b57cec5SDimitry Andric   default:
440b57cec5SDimitry Andric     return false;
450b57cec5SDimitry Andric   case TargetOpcode::G_LOAD:
460b57cec5SDimitry Andric   case TargetOpcode::G_SEXTLOAD:
47*5ffd83dbSDimitry Andric   case TargetOpcode::G_ZEXTLOAD: {
48*5ffd83dbSDimitry Andric     // Don't attempt to combine non power of 2 loads or unaligned loads when
49*5ffd83dbSDimitry Andric     // subtarget doesn't support them.
50*5ffd83dbSDimitry Andric     auto MMO = *MI.memoperands_begin();
51*5ffd83dbSDimitry Andric     const MipsSubtarget &STI =
52*5ffd83dbSDimitry Andric         static_cast<const MipsSubtarget &>(MI.getMF()->getSubtarget());
53*5ffd83dbSDimitry Andric     if (!isPowerOf2_64(MMO->getSize()))
54*5ffd83dbSDimitry Andric       return false;
55*5ffd83dbSDimitry Andric     bool isUnaligned = MMO->getAlign() < MMO->getSize();
56*5ffd83dbSDimitry Andric     if (!STI.systemSupportsUnalignedAccess() && isUnaligned)
57*5ffd83dbSDimitry Andric       return false;
58*5ffd83dbSDimitry Andric 
590b57cec5SDimitry Andric     return Helper.tryCombineExtendingLoads(MI);
600b57cec5SDimitry Andric   }
61*5ffd83dbSDimitry Andric   }
62*5ffd83dbSDimitry Andric 
630b57cec5SDimitry Andric   return false;
640b57cec5SDimitry Andric }
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric // Pass boilerplate
670b57cec5SDimitry Andric // ================
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric class MipsPreLegalizerCombiner : public MachineFunctionPass {
700b57cec5SDimitry Andric public:
710b57cec5SDimitry Andric   static char ID;
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric   MipsPreLegalizerCombiner();
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric   StringRef getPassName() const override { return "MipsPreLegalizerCombiner"; }
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric   bool runOnMachineFunction(MachineFunction &MF) override;
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override;
800b57cec5SDimitry Andric };
810b57cec5SDimitry Andric } // end anonymous namespace
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric void MipsPreLegalizerCombiner::getAnalysisUsage(AnalysisUsage &AU) const {
840b57cec5SDimitry Andric   AU.addRequired<TargetPassConfig>();
850b57cec5SDimitry Andric   AU.setPreservesCFG();
860b57cec5SDimitry Andric   getSelectionDAGFallbackAnalysisUsage(AU);
870b57cec5SDimitry Andric   MachineFunctionPass::getAnalysisUsage(AU);
880b57cec5SDimitry Andric }
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric MipsPreLegalizerCombiner::MipsPreLegalizerCombiner() : MachineFunctionPass(ID) {
910b57cec5SDimitry Andric   initializeMipsPreLegalizerCombinerPass(*PassRegistry::getPassRegistry());
920b57cec5SDimitry Andric }
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric bool MipsPreLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) {
950b57cec5SDimitry Andric   if (MF.getProperties().hasProperty(
960b57cec5SDimitry Andric           MachineFunctionProperties::Property::FailedISel))
970b57cec5SDimitry Andric     return false;
980b57cec5SDimitry Andric   auto *TPC = &getAnalysis<TargetPassConfig>();
990b57cec5SDimitry Andric   MipsPreLegalizerCombinerInfo PCInfo;
1000b57cec5SDimitry Andric   Combiner C(PCInfo, TPC);
1010b57cec5SDimitry Andric   return C.combineMachineInstrs(MF, nullptr);
1020b57cec5SDimitry Andric }
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric char MipsPreLegalizerCombiner::ID = 0;
1050b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(MipsPreLegalizerCombiner, DEBUG_TYPE,
1060b57cec5SDimitry Andric                       "Combine Mips machine instrs before legalization", false,
1070b57cec5SDimitry Andric                       false)
1080b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
1090b57cec5SDimitry Andric INITIALIZE_PASS_END(MipsPreLegalizerCombiner, DEBUG_TYPE,
1100b57cec5SDimitry Andric                     "Combine Mips machine instrs before legalization", false,
1110b57cec5SDimitry Andric                     false)
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric namespace llvm {
1140b57cec5SDimitry Andric FunctionPass *createMipsPreLegalizeCombiner() {
1150b57cec5SDimitry Andric   return new MipsPreLegalizerCombiner();
1160b57cec5SDimitry Andric }
1170b57cec5SDimitry Andric } // end namespace llvm
118