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