LLVM  12.0.0git
AArch64PreLegalizerCombiner.cpp
Go to the documentation of this file.
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"
23 #include "llvm/Support/Debug.h"
24 
25 #define DEBUG_TYPE "aarch64-prelegalizer-combiner"
26 
27 using namespace llvm;
28 using namespace MIPatternMatch;
29 
30 /// Return true if a G_FCONSTANT instruction is known to be better-represented
31 /// as a G_CONSTANT.
34  assert(MI.getOpcode() == TargetOpcode::G_FCONSTANT);
35  Register DstReg = MI.getOperand(0).getReg();
36  const unsigned DstSize = MRI.getType(DstReg).getSizeInBits();
37  if (DstSize != 32 && DstSize != 64)
38  return false;
39 
40  // When we're storing a value, it doesn't matter what register bank it's on.
41  // Since not all floating point constants can be materialized using a fmov,
42  // it makes more sense to just use a GPR.
43  return all_of(MRI.use_nodbg_instructions(DstReg),
44  [](const MachineInstr &Use) { return Use.mayStore(); });
45 }
46 
47 /// Change a G_FCONSTANT into a G_CONSTANT.
49  assert(MI.getOpcode() == TargetOpcode::G_FCONSTANT);
50  MachineIRBuilder MIB(MI);
51  const APFloat &ImmValAPF = MI.getOperand(1).getFPImm()->getValueAPF();
52  MIB.buildConstant(MI.getOperand(0).getReg(), ImmValAPF.bitcastToAPInt());
53  MI.eraseFromParent();
54 }
55 
57 protected:
59 
60 public:
62  : Helper(Helper) {}
63 };
64 
65 #define AARCH64PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_DEPS
66 #include "AArch64GenPreLegalizeGICombiner.inc"
67 #undef AARCH64PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_DEPS
68 
69 namespace {
70 #define AARCH64PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_H
71 #include "AArch64GenPreLegalizeGICombiner.inc"
72 #undef AARCH64PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_H
73 
74 class AArch64PreLegalizerCombinerInfo : public CombinerInfo {
75  GISelKnownBits *KB;
77  AArch64GenPreLegalizerCombinerHelperRuleConfig GeneratedRuleCfg;
78 
79 public:
80  AArch64PreLegalizerCombinerInfo(bool EnableOpt, bool OptSize, bool MinSize,
82  : CombinerInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false,
83  /*LegalizerInfo*/ nullptr, EnableOpt, OptSize, MinSize),
84  KB(KB), MDT(MDT) {
85  if (!GeneratedRuleCfg.parseCommandLineOption())
86  report_fatal_error("Invalid rule identifier");
87  }
88 
89  virtual bool combine(GISelChangeObserver &Observer, MachineInstr &MI,
90  MachineIRBuilder &B) const override;
91 };
92 
95  MachineIRBuilder &B) const {
96  CombinerHelper Helper(Observer, B, KB, MDT);
97  AArch64GenPreLegalizerCombinerHelper Generated(GeneratedRuleCfg, Helper);
98 
99  switch (MI.getOpcode()) {
100  case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
101  switch (MI.getIntrinsicID()) {
102  case Intrinsic::memcpy:
103  case Intrinsic::memmove:
104  case Intrinsic::memset: {
105  // If we're at -O0 set a maxlen of 32 to inline, otherwise let the other
106  // heuristics decide.
107  unsigned MaxLen = EnableOpt ? 0 : 32;
108  // Try to inline memcpy type calls if optimizations are enabled.
109  return (!EnableMinSize) ? Helper.tryCombineMemCpyFamily(MI, MaxLen)
110  : false;
111  }
112  default:
113  break;
114  }
115  }
116 
117  if (Generated.tryCombineAll(Observer, MI, B))
118  return true;
119 
120  switch (MI.getOpcode()) {
121  case TargetOpcode::G_CONCAT_VECTORS:
122  return Helper.tryCombineConcatVectors(MI);
123  case TargetOpcode::G_SHUFFLE_VECTOR:
124  return Helper.tryCombineShuffleVector(MI);
125  }
126 
127  return false;
128 }
129 
130 #define AARCH64PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_CPP
131 #include "AArch64GenPreLegalizeGICombiner.inc"
132 #undef AARCH64PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_CPP
133 
134 // Pass boilerplate
135 // ================
136 
137 class AArch64PreLegalizerCombiner : public MachineFunctionPass {
138 public:
139  static char ID;
140 
141  AArch64PreLegalizerCombiner(bool IsOptNone = false);
142 
143  StringRef getPassName() const override { return "AArch64PreLegalizerCombiner"; }
144 
145  bool runOnMachineFunction(MachineFunction &MF) override;
146 
147  void getAnalysisUsage(AnalysisUsage &AU) const override;
148 private:
149  bool IsOptNone;
150 };
151 } // end anonymous namespace
152 
153 void AArch64PreLegalizerCombiner::getAnalysisUsage(AnalysisUsage &AU) const {
155  AU.setPreservesCFG();
159  if (!IsOptNone) {
162  }
164 }
165 
166 AArch64PreLegalizerCombiner::AArch64PreLegalizerCombiner(bool IsOptNone)
167  : MachineFunctionPass(ID), IsOptNone(IsOptNone) {
169 }
170 
171 bool AArch64PreLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) {
172  if (MF.getProperties().hasProperty(
174  return false;
175  auto *TPC = &getAnalysis<TargetPassConfig>();
176  const Function &F = MF.getFunction();
177  bool EnableOpt =
178  MF.getTarget().getOptLevel() != CodeGenOpt::None && !skipFunction(F);
179  GISelKnownBits *KB = &getAnalysis<GISelKnownBitsAnalysis>().get(MF);
180  MachineDominatorTree *MDT =
181  IsOptNone ? nullptr : &getAnalysis<MachineDominatorTree>();
182  AArch64PreLegalizerCombinerInfo PCInfo(EnableOpt, F.hasOptSize(),
183  F.hasMinSize(), KB, MDT);
184  Combiner C(PCInfo, TPC);
185  return C.combineMachineInstrs(MF, /*CSEInfo*/ nullptr);
186 }
187 
189 INITIALIZE_PASS_BEGIN(AArch64PreLegalizerCombiner, DEBUG_TYPE,
190  "Combine AArch64 machine instrs before legalization",
191  false, false)
194 INITIALIZE_PASS_END(AArch64PreLegalizerCombiner, DEBUG_TYPE,
195  "Combine AArch64 machine instrs before legalization", false,
196  false)
197 
198 
199 namespace llvm {
201  return new AArch64PreLegalizerCombiner(IsOptNone);
202 }
203 } // end namespace llvm
uint64_t CallInst * C
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
Combine AArch64 machine instrs before legalization
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
coro Split coroutine into a set of functions driving its state machine
Definition: CoroSplit.cpp:1806
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:140
This class represents lattice values for constants.
Definition: AllocatorList.h:23
void getSelectionDAGFallbackAnalysisUsage(AnalysisUsage &AU)
Modify analysis usage so it preserves passes required for the SelectionDAG fallback.
Definition: Utils.cpp:509
const MachineFunctionProperties & getProperties() const
Get the function properties.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:1491
F(f)
Function & getFunction()
Return the LLVM function that this machine code represents.
AnalysisUsage & addRequired()
static void applyFConstantToConstant(MachineInstr &MI)
Change a G_FCONSTANT into a G_CONSTANT.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const ConstantFP * getFPImm() const
A Use represents the edge between a Value definition and its users.
Definition: Use.h:44
void eraseFromParent()
Unlink &#39;this&#39; from the containing basic block and delete it.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:456
Target-Independent Code Generator Pass Configuration Options.
#define DEBUG_TYPE
FunctionPass * createAArch64PreLegalizeCombiner(bool IsOptNone)
static bool matchFConstantToConstant(MachineInstr &MI, MachineRegisterInfo &MRI)
Return true if a G_FCONSTANT instruction is known to be better-represented as a G_CONSTANT.
To use KnownBitsInfo analysis in a pass, KnownBitsInfo &Info = getAnalysis<GISelKnownBitsInfoAnalysis...
Abstract class that contains various methods for clients to notify about changes. ...
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
CodeGenOpt::Level getOptLevel() const
Returns the optimization level: None, Less, Default, or Aggressive.
unsigned const MachineRegisterInfo * MRI
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
Helper class to build MachineInstr.
Represent the analysis usage information of a pass.
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:284
iterator_range< use_instr_nodbg_iterator > use_nodbg_instructions(Register Reg) const
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE, "Assign register bank of generic virtual registers", false, false) RegBankSelect
const APFloat & getValueAPF() const
Definition: Constants.h:310
INITIALIZE_PASS_BEGIN(AArch64PreLegalizerCombiner, DEBUG_TYPE, "Combine AArch64 machine instrs before legalization", false, false) INITIALIZE_PASS_END(AArch64PreLegalizerCombiner
unsigned getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition: Pass.cpp:253
void initializeAArch64PreLegalizerCombinerPass(PassRegistry &)
bool tryCombineShuffleVector(MachineInstr &MI)
Try to combine G_SHUFFLE_VECTOR into G_CONCAT_VECTORS.
vector combine
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
Representation of each machine instruction.
Definition: MachineInstr.h:62
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register...
bool tryCombineMemCpyFamily(MachineInstr &MI, unsigned MaxLen=0)
Optimize memcpy intrinsics et al, e.g.
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool hasProperty(Property P) const
unsigned getIntrinsicID() const
Returns the Intrinsic::ID for this instruction.
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
APInt bitcastToAPInt() const
Definition: APFloat.h:1130
Register getReg() const
getReg - Returns the register number.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:466
bool tryCombineConcatVectors(MachineInstr &MI)
If MI is G_CONCAT_VECTORS, try to combine it.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)