xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Mips/MipsPreLegalizerCombiner.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
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"
19*81ad6265SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h"
21480093f4SDimitry Andric #include "llvm/InitializePasses.h"
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric #define DEBUG_TYPE "mips-prelegalizer-combiner"
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric using namespace llvm;
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric namespace {
280b57cec5SDimitry Andric class MipsPreLegalizerCombinerInfo : public CombinerInfo {
290b57cec5SDimitry Andric public:
300b57cec5SDimitry Andric   MipsPreLegalizerCombinerInfo()
310b57cec5SDimitry Andric       : CombinerInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false,
328bcb0991SDimitry Andric                      /*LegalizerInfo*/ nullptr, /*EnableOpt*/ false,
338bcb0991SDimitry Andric                      /*EnableOptSize*/ false, /*EnableMinSize*/ false) {}
340b57cec5SDimitry Andric   virtual bool combine(GISelChangeObserver &Observer, MachineInstr &MI,
350b57cec5SDimitry Andric                        MachineIRBuilder &B) const override;
360b57cec5SDimitry Andric };
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric bool MipsPreLegalizerCombinerInfo::combine(GISelChangeObserver &Observer,
390b57cec5SDimitry Andric                                            MachineInstr &MI,
400b57cec5SDimitry Andric                                            MachineIRBuilder &B) const {
410b57cec5SDimitry Andric   CombinerHelper Helper(Observer, B);
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric   switch (MI.getOpcode()) {
440b57cec5SDimitry Andric   default:
450b57cec5SDimitry Andric     return false;
46fe6060f1SDimitry Andric   case TargetOpcode::G_MEMCPY_INLINE:
47fe6060f1SDimitry Andric     return Helper.tryEmitMemcpyInline(MI);
480b57cec5SDimitry Andric   case TargetOpcode::G_LOAD:
490b57cec5SDimitry Andric   case TargetOpcode::G_SEXTLOAD:
505ffd83dbSDimitry Andric   case TargetOpcode::G_ZEXTLOAD: {
515ffd83dbSDimitry Andric     // Don't attempt to combine non power of 2 loads or unaligned loads when
525ffd83dbSDimitry Andric     // subtarget doesn't support them.
535ffd83dbSDimitry Andric     auto MMO = *MI.memoperands_begin();
54*81ad6265SDimitry Andric     const MipsSubtarget &STI = MI.getMF()->getSubtarget<MipsSubtarget>();
555ffd83dbSDimitry Andric     if (!isPowerOf2_64(MMO->getSize()))
565ffd83dbSDimitry Andric       return false;
575ffd83dbSDimitry Andric     bool isUnaligned = MMO->getAlign() < MMO->getSize();
585ffd83dbSDimitry Andric     if (!STI.systemSupportsUnalignedAccess() && isUnaligned)
595ffd83dbSDimitry Andric       return false;
605ffd83dbSDimitry Andric 
610b57cec5SDimitry Andric     return Helper.tryCombineExtendingLoads(MI);
620b57cec5SDimitry Andric   }
635ffd83dbSDimitry Andric   }
645ffd83dbSDimitry Andric 
650b57cec5SDimitry Andric   return false;
660b57cec5SDimitry Andric }
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric // Pass boilerplate
690b57cec5SDimitry Andric // ================
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric class MipsPreLegalizerCombiner : public MachineFunctionPass {
720b57cec5SDimitry Andric public:
730b57cec5SDimitry Andric   static char ID;
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric   MipsPreLegalizerCombiner();
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric   StringRef getPassName() const override { return "MipsPreLegalizerCombiner"; }
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric   bool runOnMachineFunction(MachineFunction &MF) override;
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override;
820b57cec5SDimitry Andric };
830b57cec5SDimitry Andric } // end anonymous namespace
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric void MipsPreLegalizerCombiner::getAnalysisUsage(AnalysisUsage &AU) const {
860b57cec5SDimitry Andric   AU.addRequired<TargetPassConfig>();
870b57cec5SDimitry Andric   AU.setPreservesCFG();
880b57cec5SDimitry Andric   getSelectionDAGFallbackAnalysisUsage(AU);
890b57cec5SDimitry Andric   MachineFunctionPass::getAnalysisUsage(AU);
900b57cec5SDimitry Andric }
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric MipsPreLegalizerCombiner::MipsPreLegalizerCombiner() : MachineFunctionPass(ID) {
930b57cec5SDimitry Andric   initializeMipsPreLegalizerCombinerPass(*PassRegistry::getPassRegistry());
940b57cec5SDimitry Andric }
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric bool MipsPreLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) {
970b57cec5SDimitry Andric   if (MF.getProperties().hasProperty(
980b57cec5SDimitry Andric           MachineFunctionProperties::Property::FailedISel))
990b57cec5SDimitry Andric     return false;
1000b57cec5SDimitry Andric   auto *TPC = &getAnalysis<TargetPassConfig>();
1010b57cec5SDimitry Andric   MipsPreLegalizerCombinerInfo PCInfo;
1020b57cec5SDimitry Andric   Combiner C(PCInfo, TPC);
1030b57cec5SDimitry Andric   return C.combineMachineInstrs(MF, nullptr);
1040b57cec5SDimitry Andric }
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric char MipsPreLegalizerCombiner::ID = 0;
1070b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(MipsPreLegalizerCombiner, DEBUG_TYPE,
1080b57cec5SDimitry Andric                       "Combine Mips machine instrs before legalization", false,
1090b57cec5SDimitry Andric                       false)
1100b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
1110b57cec5SDimitry Andric INITIALIZE_PASS_END(MipsPreLegalizerCombiner, DEBUG_TYPE,
1120b57cec5SDimitry Andric                     "Combine Mips machine instrs before legalization", false,
1130b57cec5SDimitry Andric                     false)
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric namespace llvm {
1160b57cec5SDimitry Andric FunctionPass *createMipsPreLegalizeCombiner() {
1170b57cec5SDimitry Andric   return new MipsPreLegalizerCombiner();
1180b57cec5SDimitry Andric }
1190b57cec5SDimitry Andric } // end namespace llvm
120