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 "MipsTargetMachine.h" 15 #include "llvm/CodeGen/GlobalISel/Combiner.h" 16 #include "llvm/CodeGen/GlobalISel/CombinerHelper.h" 17 #include "llvm/CodeGen/GlobalISel/CombinerInfo.h" 18 #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h" 19 #include "llvm/CodeGen/TargetPassConfig.h" 20 #include "llvm/InitializePasses.h" 21 22 #define DEBUG_TYPE "mips-prelegalizer-combiner" 23 24 using namespace llvm; 25 26 namespace { 27 class MipsPreLegalizerCombinerInfo : public CombinerInfo { 28 public: 29 MipsPreLegalizerCombinerInfo() 30 : CombinerInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false, 31 /*LegalizerInfo*/ nullptr, /*EnableOpt*/ false, 32 /*EnableOptSize*/ false, /*EnableMinSize*/ false) {} 33 virtual bool combine(GISelChangeObserver &Observer, MachineInstr &MI, 34 MachineIRBuilder &B) const override; 35 }; 36 37 bool MipsPreLegalizerCombinerInfo::combine(GISelChangeObserver &Observer, 38 MachineInstr &MI, 39 MachineIRBuilder &B) const { 40 CombinerHelper Helper(Observer, B); 41 42 switch (MI.getOpcode()) { 43 default: 44 return false; 45 case TargetOpcode::G_MEMCPY_INLINE: 46 return Helper.tryEmitMemcpyInline(MI); 47 case TargetOpcode::G_LOAD: 48 case TargetOpcode::G_SEXTLOAD: 49 case TargetOpcode::G_ZEXTLOAD: { 50 // Don't attempt to combine non power of 2 loads or unaligned loads when 51 // subtarget doesn't support them. 52 auto MMO = *MI.memoperands_begin(); 53 const MipsSubtarget &STI = 54 static_cast<const MipsSubtarget &>(MI.getMF()->getSubtarget()); 55 if (!isPowerOf2_64(MMO->getSize())) 56 return false; 57 bool isUnaligned = MMO->getAlign() < MMO->getSize(); 58 if (!STI.systemSupportsUnalignedAccess() && isUnaligned) 59 return false; 60 61 return Helper.tryCombineExtendingLoads(MI); 62 } 63 } 64 65 return false; 66 } 67 68 // Pass boilerplate 69 // ================ 70 71 class MipsPreLegalizerCombiner : public MachineFunctionPass { 72 public: 73 static char ID; 74 75 MipsPreLegalizerCombiner(); 76 77 StringRef getPassName() const override { return "MipsPreLegalizerCombiner"; } 78 79 bool runOnMachineFunction(MachineFunction &MF) override; 80 81 void getAnalysisUsage(AnalysisUsage &AU) const override; 82 }; 83 } // end anonymous namespace 84 85 void MipsPreLegalizerCombiner::getAnalysisUsage(AnalysisUsage &AU) const { 86 AU.addRequired<TargetPassConfig>(); 87 AU.setPreservesCFG(); 88 getSelectionDAGFallbackAnalysisUsage(AU); 89 MachineFunctionPass::getAnalysisUsage(AU); 90 } 91 92 MipsPreLegalizerCombiner::MipsPreLegalizerCombiner() : MachineFunctionPass(ID) { 93 initializeMipsPreLegalizerCombinerPass(*PassRegistry::getPassRegistry()); 94 } 95 96 bool MipsPreLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) { 97 if (MF.getProperties().hasProperty( 98 MachineFunctionProperties::Property::FailedISel)) 99 return false; 100 auto *TPC = &getAnalysis<TargetPassConfig>(); 101 MipsPreLegalizerCombinerInfo PCInfo; 102 Combiner C(PCInfo, TPC); 103 return C.combineMachineInstrs(MF, nullptr); 104 } 105 106 char MipsPreLegalizerCombiner::ID = 0; 107 INITIALIZE_PASS_BEGIN(MipsPreLegalizerCombiner, DEBUG_TYPE, 108 "Combine Mips machine instrs before legalization", false, 109 false) 110 INITIALIZE_PASS_DEPENDENCY(TargetPassConfig) 111 INITIALIZE_PASS_END(MipsPreLegalizerCombiner, DEBUG_TYPE, 112 "Combine Mips machine instrs before legalization", false, 113 false) 114 115 namespace llvm { 116 FunctionPass *createMipsPreLegalizeCombiner() { 117 return new MipsPreLegalizerCombiner(); 118 } 119 } // end namespace llvm 120