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