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: 89 case TargetOpcode::G_MEMMOVE: 90 case TargetOpcode::G_MEMSET: { 91 // At -O0 set a maxlen of 32 to inline; 92 unsigned MaxLen = 32; 93 // Try to inline memcpy type calls if optimizations are enabled. 94 if (Helper.tryCombineMemCpyFamily(MI, MaxLen)) 95 return true; 96 if (Opc == TargetOpcode::G_MEMSET) 97 return llvm::AArch64GISelUtils::tryEmitBZero(MI, B, EnableMinSize); 98 return false; 99 } 100 } 101 102 return false; 103 } 104 105 #define AARCH64O0PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_CPP 106 #include "AArch64GenO0PreLegalizeGICombiner.inc" 107 #undef AARCH64O0PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_CPP 108 109 // Pass boilerplate 110 // ================ 111 112 class AArch64O0PreLegalizerCombiner : public MachineFunctionPass { 113 public: 114 static char ID; 115 116 AArch64O0PreLegalizerCombiner(); 117 118 StringRef getPassName() const override { 119 return "AArch64O0PreLegalizerCombiner"; 120 } 121 122 bool runOnMachineFunction(MachineFunction &MF) override; 123 124 void getAnalysisUsage(AnalysisUsage &AU) const override; 125 }; 126 } // end anonymous namespace 127 128 void AArch64O0PreLegalizerCombiner::getAnalysisUsage(AnalysisUsage &AU) const { 129 AU.addRequired<TargetPassConfig>(); 130 AU.setPreservesCFG(); 131 getSelectionDAGFallbackAnalysisUsage(AU); 132 AU.addRequired<GISelKnownBitsAnalysis>(); 133 AU.addPreserved<GISelKnownBitsAnalysis>(); 134 MachineFunctionPass::getAnalysisUsage(AU); 135 } 136 137 AArch64O0PreLegalizerCombiner::AArch64O0PreLegalizerCombiner() 138 : MachineFunctionPass(ID) { 139 initializeAArch64O0PreLegalizerCombinerPass(*PassRegistry::getPassRegistry()); 140 } 141 142 bool AArch64O0PreLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) { 143 if (MF.getProperties().hasProperty( 144 MachineFunctionProperties::Property::FailedISel)) 145 return false; 146 auto &TPC = getAnalysis<TargetPassConfig>(); 147 148 const Function &F = MF.getFunction(); 149 GISelKnownBits *KB = &getAnalysis<GISelKnownBitsAnalysis>().get(MF); 150 AArch64O0PreLegalizerCombinerInfo PCInfo( 151 false, F.hasOptSize(), F.hasMinSize(), KB, nullptr /* MDT */); 152 Combiner C(PCInfo, &TPC); 153 return C.combineMachineInstrs(MF, nullptr /* CSEInfo */); 154 } 155 156 char AArch64O0PreLegalizerCombiner::ID = 0; 157 INITIALIZE_PASS_BEGIN(AArch64O0PreLegalizerCombiner, DEBUG_TYPE, 158 "Combine AArch64 machine instrs before legalization", 159 false, false) 160 INITIALIZE_PASS_DEPENDENCY(TargetPassConfig) 161 INITIALIZE_PASS_DEPENDENCY(GISelKnownBitsAnalysis) 162 INITIALIZE_PASS_DEPENDENCY(GISelCSEAnalysisWrapperPass) 163 INITIALIZE_PASS_END(AArch64O0PreLegalizerCombiner, DEBUG_TYPE, 164 "Combine AArch64 machine instrs before legalization", false, 165 false) 166 167 namespace llvm { 168 FunctionPass *createAArch64O0PreLegalizerCombiner() { 169 return new AArch64O0PreLegalizerCombiner(); 170 } 171 } // end namespace llvm 172