LLVM  11.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 
56 #define AARCH64PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_DEPS
57 #include "AArch64GenPreLegalizeGICombiner.inc"
58 #undef AARCH64PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_DEPS
59 
60 namespace {
61 #define AARCH64PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_H
62 #include "AArch64GenPreLegalizeGICombiner.inc"
63 #undef AARCH64PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_H
64 
65 class AArch64PreLegalizerCombinerInfo : public CombinerInfo {
66  GISelKnownBits *KB;
68 
69 public:
70  AArch64GenPreLegalizerCombinerHelper Generated;
71 
72  AArch64PreLegalizerCombinerInfo(bool EnableOpt, bool OptSize, bool MinSize,
74  : CombinerInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false,
75  /*LegalizerInfo*/ nullptr, EnableOpt, OptSize, MinSize),
76  KB(KB), MDT(MDT) {
77  if (!Generated.parseCommandLineOption())
78  report_fatal_error("Invalid rule identifier");
79  }
80 
81  virtual bool combine(GISelChangeObserver &Observer, MachineInstr &MI,
82  MachineIRBuilder &B) const override;
83 };
84 
87  MachineIRBuilder &B) const {
88  CombinerHelper Helper(Observer, B, KB, MDT);
89 
90  switch (MI.getOpcode()) {
91  case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
92  switch (MI.getIntrinsicID()) {
93  case Intrinsic::memcpy:
94  case Intrinsic::memmove:
95  case Intrinsic::memset: {
96  // If we're at -O0 set a maxlen of 32 to inline, otherwise let the other
97  // heuristics decide.
98  unsigned MaxLen = EnableOpt ? 0 : 32;
99  // Try to inline memcpy type calls if optimizations are enabled.
100  return (!EnableMinSize) ? Helper.tryCombineMemCpyFamily(MI, MaxLen)
101  : false;
102  }
103  default:
104  break;
105  }
106  }
107 
108  if (Generated.tryCombineAll(Observer, MI, B, Helper))
109  return true;
110 
111  switch (MI.getOpcode()) {
112  case TargetOpcode::G_CONCAT_VECTORS:
113  return Helper.tryCombineConcatVectors(MI);
114  case TargetOpcode::G_SHUFFLE_VECTOR:
115  return Helper.tryCombineShuffleVector(MI);
116  }
117 
118  return false;
119 }
120 
121 #define AARCH64PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_CPP
122 #include "AArch64GenPreLegalizeGICombiner.inc"
123 #undef AARCH64PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_CPP
124 
125 // Pass boilerplate
126 // ================
127 
128 class AArch64PreLegalizerCombiner : public MachineFunctionPass {
129 public:
130  static char ID;
131 
132  AArch64PreLegalizerCombiner(bool IsOptNone = false);
133 
134  StringRef getPassName() const override { return "AArch64PreLegalizerCombiner"; }
135 
136  bool runOnMachineFunction(MachineFunction &MF) override;
137 
138  void getAnalysisUsage(AnalysisUsage &AU) const override;
139 private:
140  bool IsOptNone;
141 };
142 } // end anonymous namespace
143 
144 void AArch64PreLegalizerCombiner::getAnalysisUsage(AnalysisUsage &AU) const {
146  AU.setPreservesCFG();
150  if (!IsOptNone) {
153  }
155 }
156 
157 AArch64PreLegalizerCombiner::AArch64PreLegalizerCombiner(bool IsOptNone)
158  : MachineFunctionPass(ID), IsOptNone(IsOptNone) {
160 }
161 
162 bool AArch64PreLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) {
163  if (MF.getProperties().hasProperty(
165  return false;
166  auto *TPC = &getAnalysis<TargetPassConfig>();
167  const Function &F = MF.getFunction();
168  bool EnableOpt =
169  MF.getTarget().getOptLevel() != CodeGenOpt::None && !skipFunction(F);
170  GISelKnownBits *KB = &getAnalysis<GISelKnownBitsAnalysis>().get(MF);
171  MachineDominatorTree *MDT =
172  IsOptNone ? nullptr : &getAnalysis<MachineDominatorTree>();
173  AArch64PreLegalizerCombinerInfo PCInfo(EnableOpt, F.hasOptSize(),
174  F.hasMinSize(), KB, MDT);
175  Combiner C(PCInfo, TPC);
176  return C.combineMachineInstrs(MF, /*CSEInfo*/ nullptr);
177 }
178 
180 INITIALIZE_PASS_BEGIN(AArch64PreLegalizerCombiner, DEBUG_TYPE,
181  "Combine AArch64 machine instrs before legalization",
182  false, false)
185 INITIALIZE_PASS_END(AArch64PreLegalizerCombiner, DEBUG_TYPE,
186  "Combine AArch64 machine instrs before legalization", false,
187  false)
188 
189 
190 namespace llvm {
192  return new AArch64PreLegalizerCombiner(IsOptNone);
193 }
194 } // 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:504
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:1483
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:435
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:281
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:305
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:440
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)