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