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