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: 320b57cec5SDimitry 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: 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 535f757f3fSDimitry Andric static const char *getName() { return "MipsPreLegalizerCombiner"; } 545f757f3fSDimitry Andric 555f757f3fSDimitry Andric void setupGeneratedPerFunctionState(MachineFunction &MF) override { 565f757f3fSDimitry Andric // TODO: TableGen-erate this class' impl. 575f757f3fSDimitry Andric } 585f757f3fSDimitry Andric 595f757f3fSDimitry 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 970b57cec5SDimitry 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 1050b57cec5SDimitry 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 1140b57cec5SDimitry Andric MipsPreLegalizerCombiner::MipsPreLegalizerCombiner() : MachineFunctionPass(ID) { 1150b57cec5SDimitry Andric initializeMipsPreLegalizerCombinerPass(*PassRegistry::getPassRegistry()); 1160b57cec5SDimitry Andric } 1170b57cec5SDimitry Andric 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 { 1460b57cec5SDimitry Andric FunctionPass *createMipsPreLegalizeCombiner() { 1470b57cec5SDimitry Andric return new MipsPreLegalizerCombiner(); 1480b57cec5SDimitry Andric } 1490b57cec5SDimitry Andric } // end namespace llvm 150