1 //=== lib/CodeGen/GlobalISel/AArch64O0PreLegalizerCombiner.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 "AArch64GlobalISelUtils.h" 15 #include "AArch64TargetMachine.h" 16 #include "llvm/CodeGen/GlobalISel/Combiner.h" 17 #include "llvm/CodeGen/GlobalISel/CombinerHelper.h" 18 #include "llvm/CodeGen/GlobalISel/CombinerInfo.h" 19 #include "llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h" 20 #include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h" 21 #include "llvm/CodeGen/GlobalISel/GISelKnownBits.h" 22 #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h" 23 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" 24 #include "llvm/CodeGen/MachineDominators.h" 25 #include "llvm/CodeGen/MachineFunction.h" 26 #include "llvm/CodeGen/MachineFunctionPass.h" 27 #include "llvm/CodeGen/MachineRegisterInfo.h" 28 #include "llvm/CodeGen/TargetPassConfig.h" 29 #include "llvm/IR/Instructions.h" 30 #include "llvm/Support/Debug.h" 31 32 #define GET_GICOMBINER_DEPS 33 #include "AArch64GenO0PreLegalizeGICombiner.inc" 34 #undef GET_GICOMBINER_DEPS 35 36 #define DEBUG_TYPE "aarch64-O0-prelegalizer-combiner" 37 38 using namespace llvm; 39 using namespace MIPatternMatch; 40 namespace { 41 #define GET_GICOMBINER_TYPES 42 #include "AArch64GenO0PreLegalizeGICombiner.inc" 43 #undef GET_GICOMBINER_TYPES 44 45 class AArch64O0PreLegalizerCombinerImpl : public GIMatchTableExecutor { 46 protected: 47 CombinerHelper &Helper; 48 const AArch64O0PreLegalizerCombinerImplRuleConfig &RuleConfig; 49 50 const AArch64Subtarget &STI; 51 GISelChangeObserver &Observer; 52 MachineIRBuilder &B; 53 MachineFunction &MF; 54 55 MachineRegisterInfo &MRI; 56 57 public: 58 AArch64O0PreLegalizerCombinerImpl( 59 const AArch64O0PreLegalizerCombinerImplRuleConfig &RuleConfig, 60 GISelChangeObserver &Observer, MachineIRBuilder &B, 61 CombinerHelper &Helper); 62 63 static const char *getName() { return "AArch64O0PreLegalizerCombiner"; } 64 65 bool tryCombineAll(MachineInstr &I) const; 66 67 private: 68 #define GET_GICOMBINER_CLASS_MEMBERS 69 #include "AArch64GenO0PreLegalizeGICombiner.inc" 70 #undef GET_GICOMBINER_CLASS_MEMBERS 71 }; 72 73 #define GET_GICOMBINER_IMPL 74 #include "AArch64GenO0PreLegalizeGICombiner.inc" 75 #undef GET_GICOMBINER_IMPL 76 77 AArch64O0PreLegalizerCombinerImpl::AArch64O0PreLegalizerCombinerImpl( 78 const AArch64O0PreLegalizerCombinerImplRuleConfig &RuleConfig, 79 GISelChangeObserver &Observer, MachineIRBuilder &B, CombinerHelper &Helper) 80 : Helper(Helper), RuleConfig(RuleConfig), 81 STI(B.getMF().getSubtarget<AArch64Subtarget>()), Observer(Observer), B(B), 82 MF(B.getMF()), MRI(*B.getMRI()), 83 #define GET_GICOMBINER_CONSTRUCTOR_INITS 84 #include "AArch64GenO0PreLegalizeGICombiner.inc" 85 #undef GET_GICOMBINER_CONSTRUCTOR_INITS 86 { 87 } 88 89 class AArch64O0PreLegalizerCombinerInfo : public CombinerInfo { 90 GISelKnownBits *KB; 91 MachineDominatorTree *MDT; 92 AArch64O0PreLegalizerCombinerImplRuleConfig RuleConfig; 93 94 public: 95 AArch64O0PreLegalizerCombinerInfo(bool EnableOpt, bool OptSize, bool MinSize, 96 GISelKnownBits *KB, 97 MachineDominatorTree *MDT) 98 : CombinerInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false, 99 /*LegalizerInfo*/ nullptr, EnableOpt, OptSize, MinSize), 100 KB(KB), MDT(MDT) { 101 if (!RuleConfig.parseCommandLineOption()) 102 report_fatal_error("Invalid rule identifier"); 103 } 104 105 bool combine(GISelChangeObserver &Observer, MachineInstr &MI, 106 MachineIRBuilder &B) const override; 107 }; 108 109 bool AArch64O0PreLegalizerCombinerInfo::combine(GISelChangeObserver &Observer, 110 MachineInstr &MI, 111 MachineIRBuilder &B) const { 112 CombinerHelper Helper(Observer, B, /*IsPreLegalize*/ true, KB, MDT); 113 AArch64O0PreLegalizerCombinerImpl Impl(RuleConfig, Observer, B, Helper); 114 Impl.setupMF(*MI.getMF(), KB); 115 116 if (Impl.tryCombineAll(MI)) 117 return true; 118 119 unsigned Opc = MI.getOpcode(); 120 switch (Opc) { 121 case TargetOpcode::G_CONCAT_VECTORS: 122 return Helper.tryCombineConcatVectors(MI); 123 case TargetOpcode::G_SHUFFLE_VECTOR: 124 return Helper.tryCombineShuffleVector(MI); 125 case TargetOpcode::G_MEMCPY_INLINE: 126 return Helper.tryEmitMemcpyInline(MI); 127 case TargetOpcode::G_MEMCPY: 128 case TargetOpcode::G_MEMMOVE: 129 case TargetOpcode::G_MEMSET: { 130 // At -O0 set a maxlen of 32 to inline; 131 unsigned MaxLen = 32; 132 // Try to inline memcpy type calls if optimizations are enabled. 133 if (Helper.tryCombineMemCpyFamily(MI, MaxLen)) 134 return true; 135 if (Opc == TargetOpcode::G_MEMSET) 136 return llvm::AArch64GISelUtils::tryEmitBZero(MI, B, EnableMinSize); 137 return false; 138 } 139 } 140 141 return false; 142 } 143 144 // Pass boilerplate 145 // ================ 146 147 class AArch64O0PreLegalizerCombiner : public MachineFunctionPass { 148 public: 149 static char ID; 150 151 AArch64O0PreLegalizerCombiner(); 152 153 StringRef getPassName() const override { 154 return "AArch64O0PreLegalizerCombiner"; 155 } 156 157 bool runOnMachineFunction(MachineFunction &MF) override; 158 159 void getAnalysisUsage(AnalysisUsage &AU) const override; 160 }; 161 } // end anonymous namespace 162 163 void AArch64O0PreLegalizerCombiner::getAnalysisUsage(AnalysisUsage &AU) const { 164 AU.addRequired<TargetPassConfig>(); 165 AU.setPreservesCFG(); 166 getSelectionDAGFallbackAnalysisUsage(AU); 167 AU.addRequired<GISelKnownBitsAnalysis>(); 168 AU.addPreserved<GISelKnownBitsAnalysis>(); 169 MachineFunctionPass::getAnalysisUsage(AU); 170 } 171 172 AArch64O0PreLegalizerCombiner::AArch64O0PreLegalizerCombiner() 173 : MachineFunctionPass(ID) { 174 initializeAArch64O0PreLegalizerCombinerPass(*PassRegistry::getPassRegistry()); 175 } 176 177 bool AArch64O0PreLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) { 178 if (MF.getProperties().hasProperty( 179 MachineFunctionProperties::Property::FailedISel)) 180 return false; 181 auto &TPC = getAnalysis<TargetPassConfig>(); 182 183 const Function &F = MF.getFunction(); 184 GISelKnownBits *KB = &getAnalysis<GISelKnownBitsAnalysis>().get(MF); 185 AArch64O0PreLegalizerCombinerInfo PCInfo( 186 false, F.hasOptSize(), F.hasMinSize(), KB, nullptr /* MDT */); 187 Combiner C(PCInfo, &TPC); 188 return C.combineMachineInstrs(MF, nullptr /* CSEInfo */); 189 } 190 191 char AArch64O0PreLegalizerCombiner::ID = 0; 192 INITIALIZE_PASS_BEGIN(AArch64O0PreLegalizerCombiner, DEBUG_TYPE, 193 "Combine AArch64 machine instrs before legalization", 194 false, false) 195 INITIALIZE_PASS_DEPENDENCY(TargetPassConfig) 196 INITIALIZE_PASS_DEPENDENCY(GISelKnownBitsAnalysis) 197 INITIALIZE_PASS_DEPENDENCY(GISelCSEAnalysisWrapperPass) 198 INITIALIZE_PASS_END(AArch64O0PreLegalizerCombiner, DEBUG_TYPE, 199 "Combine AArch64 machine instrs before legalization", false, 200 false) 201 202 namespace llvm { 203 FunctionPass *createAArch64O0PreLegalizerCombiner() { 204 return new AArch64O0PreLegalizerCombiner(); 205 } 206 } // end namespace llvm 207