1fe6060f1SDimitry Andric //=== lib/CodeGen/GlobalISel/AArch64O0PreLegalizerCombiner.cpp ------------===// 2fe6060f1SDimitry Andric // 3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6fe6060f1SDimitry Andric // 7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 8fe6060f1SDimitry Andric // 9fe6060f1SDimitry Andric // This pass does combining of machine instructions at the generic MI level, 10fe6060f1SDimitry Andric // before the legalizer. 11fe6060f1SDimitry Andric // 12fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 13fe6060f1SDimitry Andric 14fe6060f1SDimitry Andric #include "AArch64GlobalISelUtils.h" 15fe6060f1SDimitry Andric #include "AArch64TargetMachine.h" 16fe6060f1SDimitry Andric #include "llvm/CodeGen/GlobalISel/Combiner.h" 17fe6060f1SDimitry Andric #include "llvm/CodeGen/GlobalISel/CombinerHelper.h" 18fe6060f1SDimitry Andric #include "llvm/CodeGen/GlobalISel/CombinerInfo.h" 1906c3fb27SDimitry Andric #include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h" 20fe6060f1SDimitry Andric #include "llvm/CodeGen/GlobalISel/GISelKnownBits.h" 21fe6060f1SDimitry Andric #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h" 22fe6060f1SDimitry Andric #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" 23fe6060f1SDimitry Andric #include "llvm/CodeGen/MachineDominators.h" 24fe6060f1SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 25fe6060f1SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 26fe6060f1SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 27fe6060f1SDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h" 28fe6060f1SDimitry Andric #include "llvm/IR/Instructions.h" 29fe6060f1SDimitry Andric #include "llvm/Support/Debug.h" 30fe6060f1SDimitry Andric 3106c3fb27SDimitry Andric #define GET_GICOMBINER_DEPS 3206c3fb27SDimitry Andric #include "AArch64GenO0PreLegalizeGICombiner.inc" 3306c3fb27SDimitry Andric #undef GET_GICOMBINER_DEPS 3406c3fb27SDimitry Andric 35fe6060f1SDimitry Andric #define DEBUG_TYPE "aarch64-O0-prelegalizer-combiner" 36fe6060f1SDimitry Andric 37fe6060f1SDimitry Andric using namespace llvm; 38fe6060f1SDimitry Andric using namespace MIPatternMatch; 3906c3fb27SDimitry Andric namespace { 4006c3fb27SDimitry Andric #define GET_GICOMBINER_TYPES 4106c3fb27SDimitry Andric #include "AArch64GenO0PreLegalizeGICombiner.inc" 4206c3fb27SDimitry Andric #undef GET_GICOMBINER_TYPES 43fe6060f1SDimitry Andric 445f757f3fSDimitry Andric class AArch64O0PreLegalizerCombinerImpl : public Combiner { 45fe6060f1SDimitry Andric protected: 465f757f3fSDimitry Andric // TODO: Make CombinerHelper methods const. 475f757f3fSDimitry Andric mutable CombinerHelper Helper; 4806c3fb27SDimitry Andric const AArch64O0PreLegalizerCombinerImplRuleConfig &RuleConfig; 4906c3fb27SDimitry Andric const AArch64Subtarget &STI; 50fe6060f1SDimitry Andric 51fe6060f1SDimitry Andric public: 5206c3fb27SDimitry Andric AArch64O0PreLegalizerCombinerImpl( 535f757f3fSDimitry Andric MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC, 545f757f3fSDimitry Andric GISelKnownBits &KB, GISelCSEInfo *CSEInfo, 5506c3fb27SDimitry Andric const AArch64O0PreLegalizerCombinerImplRuleConfig &RuleConfig, 565f757f3fSDimitry Andric const AArch64Subtarget &STI); 5706c3fb27SDimitry Andric 5806c3fb27SDimitry Andric static const char *getName() { return "AArch64O0PreLegalizerCombiner"; } 5906c3fb27SDimitry Andric 605f757f3fSDimitry Andric bool tryCombineAll(MachineInstr &I) const override; 615f757f3fSDimitry Andric 625f757f3fSDimitry Andric bool tryCombineAllImpl(MachineInstr &I) const; 6306c3fb27SDimitry Andric 6406c3fb27SDimitry Andric private: 6506c3fb27SDimitry Andric #define GET_GICOMBINER_CLASS_MEMBERS 6606c3fb27SDimitry Andric #include "AArch64GenO0PreLegalizeGICombiner.inc" 6706c3fb27SDimitry Andric #undef GET_GICOMBINER_CLASS_MEMBERS 68fe6060f1SDimitry Andric }; 69fe6060f1SDimitry Andric 7006c3fb27SDimitry Andric #define GET_GICOMBINER_IMPL 71fe6060f1SDimitry Andric #include "AArch64GenO0PreLegalizeGICombiner.inc" 7206c3fb27SDimitry Andric #undef GET_GICOMBINER_IMPL 73fe6060f1SDimitry Andric 7406c3fb27SDimitry Andric AArch64O0PreLegalizerCombinerImpl::AArch64O0PreLegalizerCombinerImpl( 755f757f3fSDimitry Andric MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC, 765f757f3fSDimitry Andric GISelKnownBits &KB, GISelCSEInfo *CSEInfo, 7706c3fb27SDimitry Andric const AArch64O0PreLegalizerCombinerImplRuleConfig &RuleConfig, 785f757f3fSDimitry Andric const AArch64Subtarget &STI) 795f757f3fSDimitry Andric : Combiner(MF, CInfo, TPC, &KB, CSEInfo), 805f757f3fSDimitry Andric Helper(Observer, B, /*IsPreLegalize*/ true, &KB), RuleConfig(RuleConfig), 815f757f3fSDimitry Andric STI(STI), 8206c3fb27SDimitry Andric #define GET_GICOMBINER_CONSTRUCTOR_INITS 83fe6060f1SDimitry Andric #include "AArch64GenO0PreLegalizeGICombiner.inc" 8406c3fb27SDimitry Andric #undef GET_GICOMBINER_CONSTRUCTOR_INITS 8506c3fb27SDimitry Andric { 8606c3fb27SDimitry Andric } 87fe6060f1SDimitry Andric 885f757f3fSDimitry Andric bool AArch64O0PreLegalizerCombinerImpl::tryCombineAll(MachineInstr &MI) const { 895f757f3fSDimitry Andric if (tryCombineAllImpl(MI)) 90fe6060f1SDimitry Andric return true; 91fe6060f1SDimitry Andric 92fe6060f1SDimitry Andric unsigned Opc = MI.getOpcode(); 93fe6060f1SDimitry Andric switch (Opc) { 94fe6060f1SDimitry Andric case TargetOpcode::G_SHUFFLE_VECTOR: 95fe6060f1SDimitry Andric return Helper.tryCombineShuffleVector(MI); 96fe6060f1SDimitry Andric case TargetOpcode::G_MEMCPY_INLINE: 97fe6060f1SDimitry Andric return Helper.tryEmitMemcpyInline(MI); 98fe6060f1SDimitry Andric case TargetOpcode::G_MEMCPY: 99fe6060f1SDimitry Andric case TargetOpcode::G_MEMMOVE: 100fe6060f1SDimitry Andric case TargetOpcode::G_MEMSET: { 101fe6060f1SDimitry Andric // At -O0 set a maxlen of 32 to inline; 102fe6060f1SDimitry Andric unsigned MaxLen = 32; 103fe6060f1SDimitry Andric // Try to inline memcpy type calls if optimizations are enabled. 104fe6060f1SDimitry Andric if (Helper.tryCombineMemCpyFamily(MI, MaxLen)) 105fe6060f1SDimitry Andric return true; 106fe6060f1SDimitry Andric if (Opc == TargetOpcode::G_MEMSET) 1075f757f3fSDimitry Andric return llvm::AArch64GISelUtils::tryEmitBZero(MI, B, CInfo.EnableMinSize); 108fe6060f1SDimitry Andric return false; 109fe6060f1SDimitry Andric } 110fe6060f1SDimitry Andric } 111fe6060f1SDimitry Andric 112fe6060f1SDimitry Andric return false; 113fe6060f1SDimitry Andric } 114fe6060f1SDimitry Andric 115fe6060f1SDimitry Andric // Pass boilerplate 116fe6060f1SDimitry Andric // ================ 117fe6060f1SDimitry Andric 118fe6060f1SDimitry Andric class AArch64O0PreLegalizerCombiner : public MachineFunctionPass { 119fe6060f1SDimitry Andric public: 120fe6060f1SDimitry Andric static char ID; 121fe6060f1SDimitry Andric 122fe6060f1SDimitry Andric AArch64O0PreLegalizerCombiner(); 123fe6060f1SDimitry Andric 124fe6060f1SDimitry Andric StringRef getPassName() const override { 125fe6060f1SDimitry Andric return "AArch64O0PreLegalizerCombiner"; 126fe6060f1SDimitry Andric } 127fe6060f1SDimitry Andric 128fe6060f1SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override; 129fe6060f1SDimitry Andric 130fe6060f1SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override; 1315f757f3fSDimitry Andric 1325f757f3fSDimitry Andric private: 1335f757f3fSDimitry Andric AArch64O0PreLegalizerCombinerImplRuleConfig RuleConfig; 134fe6060f1SDimitry Andric }; 135fe6060f1SDimitry Andric } // end anonymous namespace 136fe6060f1SDimitry Andric 137fe6060f1SDimitry Andric void AArch64O0PreLegalizerCombiner::getAnalysisUsage(AnalysisUsage &AU) const { 138fe6060f1SDimitry Andric AU.addRequired<TargetPassConfig>(); 139fe6060f1SDimitry Andric AU.setPreservesCFG(); 140fe6060f1SDimitry Andric getSelectionDAGFallbackAnalysisUsage(AU); 141fe6060f1SDimitry Andric AU.addRequired<GISelKnownBitsAnalysis>(); 142fe6060f1SDimitry Andric AU.addPreserved<GISelKnownBitsAnalysis>(); 143fe6060f1SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 144fe6060f1SDimitry Andric } 145fe6060f1SDimitry Andric 146fe6060f1SDimitry Andric AArch64O0PreLegalizerCombiner::AArch64O0PreLegalizerCombiner() 147fe6060f1SDimitry Andric : MachineFunctionPass(ID) { 148fe6060f1SDimitry Andric initializeAArch64O0PreLegalizerCombinerPass(*PassRegistry::getPassRegistry()); 1495f757f3fSDimitry Andric 1505f757f3fSDimitry Andric if (!RuleConfig.parseCommandLineOption()) 1515f757f3fSDimitry Andric report_fatal_error("Invalid rule identifier"); 152fe6060f1SDimitry Andric } 153fe6060f1SDimitry Andric 154fe6060f1SDimitry Andric bool AArch64O0PreLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) { 155fe6060f1SDimitry Andric if (MF.getProperties().hasProperty( 156fe6060f1SDimitry Andric MachineFunctionProperties::Property::FailedISel)) 157fe6060f1SDimitry Andric return false; 158fe6060f1SDimitry Andric auto &TPC = getAnalysis<TargetPassConfig>(); 159fe6060f1SDimitry Andric 160fe6060f1SDimitry Andric const Function &F = MF.getFunction(); 161fe6060f1SDimitry Andric GISelKnownBits *KB = &getAnalysis<GISelKnownBitsAnalysis>().get(MF); 1625f757f3fSDimitry Andric 1635f757f3fSDimitry Andric const AArch64Subtarget &ST = MF.getSubtarget<AArch64Subtarget>(); 1645f757f3fSDimitry Andric 1655f757f3fSDimitry Andric CombinerInfo CInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false, 1665f757f3fSDimitry Andric /*LegalizerInfo*/ nullptr, /*EnableOpt*/ false, 1675f757f3fSDimitry Andric F.hasOptSize(), F.hasMinSize()); 168*0fca6ea1SDimitry Andric // Disable fixed-point iteration in the Combiner. This improves compile-time 169*0fca6ea1SDimitry Andric // at the cost of possibly missing optimizations. See PR#94291 for details. 170*0fca6ea1SDimitry Andric CInfo.MaxIterations = 1; 171*0fca6ea1SDimitry Andric 1725f757f3fSDimitry Andric AArch64O0PreLegalizerCombinerImpl Impl(MF, CInfo, &TPC, *KB, 1735f757f3fSDimitry Andric /*CSEInfo*/ nullptr, RuleConfig, ST); 1745f757f3fSDimitry Andric return Impl.combineMachineInstrs(); 175fe6060f1SDimitry Andric } 176fe6060f1SDimitry Andric 177fe6060f1SDimitry Andric char AArch64O0PreLegalizerCombiner::ID = 0; 178fe6060f1SDimitry Andric INITIALIZE_PASS_BEGIN(AArch64O0PreLegalizerCombiner, DEBUG_TYPE, 179fe6060f1SDimitry Andric "Combine AArch64 machine instrs before legalization", 180fe6060f1SDimitry Andric false, false) 181fe6060f1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(TargetPassConfig) 182fe6060f1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(GISelKnownBitsAnalysis) 183fe6060f1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(GISelCSEAnalysisWrapperPass) 184fe6060f1SDimitry Andric INITIALIZE_PASS_END(AArch64O0PreLegalizerCombiner, DEBUG_TYPE, 185fe6060f1SDimitry Andric "Combine AArch64 machine instrs before legalization", false, 186fe6060f1SDimitry Andric false) 187fe6060f1SDimitry Andric 188fe6060f1SDimitry Andric namespace llvm { 189fe6060f1SDimitry Andric FunctionPass *createAArch64O0PreLegalizerCombiner() { 190fe6060f1SDimitry Andric return new AArch64O0PreLegalizerCombiner(); 191fe6060f1SDimitry Andric } 192fe6060f1SDimitry Andric } // end namespace llvm 193