Home | History | Annotate | Line # | Download | only in GISel
      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