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