1 //=== lib/CodeGen/GlobalISel/AArch64PreLegalizerCombiner.cpp --------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This pass does combining of machine instructions at the generic MI level,
10 // before the legalizer.
12 //===----------------------------------------------------------------------===//
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"
25 #define DEBUG_TYPE "aarch64-prelegalizer-combiner"
28 using namespace MIPatternMatch;
30 /// Return true if a G_FCONSTANT instruction is known to be better-represented
32 static bool matchFConstantToConstant(MachineInstr &MI,
33 MachineRegisterInfo &MRI) {
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)
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(); });
47 /// Change a G_FCONSTANT into a G_CONSTANT.
48 static void applyFConstantToConstant(MachineInstr &MI) {
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());
56 class AArch64PreLegalizerCombinerHelperState {
58 CombinerHelper &Helper;
61 AArch64PreLegalizerCombinerHelperState(CombinerHelper &Helper)
65 #define AARCH64PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_DEPS
66 #include "AArch64GenPreLegalizeGICombiner.inc"
67 #undef AARCH64PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_DEPS
70 #define AARCH64PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_H
71 #include "AArch64GenPreLegalizeGICombiner.inc"
72 #undef AARCH64PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_H
74 class AArch64PreLegalizerCombinerInfo : public CombinerInfo {
76 MachineDominatorTree *MDT;
77 AArch64GenPreLegalizerCombinerHelperRuleConfig GeneratedRuleCfg;
80 AArch64PreLegalizerCombinerInfo(bool EnableOpt, bool OptSize, bool MinSize,
81 GISelKnownBits *KB, MachineDominatorTree *MDT)
82 : CombinerInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false,
83 /*LegalizerInfo*/ nullptr, EnableOpt, OptSize, MinSize),
85 if (!GeneratedRuleCfg.parseCommandLineOption())
86 report_fatal_error("Invalid rule identifier");
89 virtual bool combine(GISelChangeObserver &Observer, MachineInstr &MI,
90 MachineIRBuilder &B) const override;
93 bool AArch64PreLegalizerCombinerInfo::combine(GISelChangeObserver &Observer,
95 MachineIRBuilder &B) const {
96 CombinerHelper Helper(Observer, B, KB, MDT);
97 AArch64GenPreLegalizerCombinerHelper Generated(GeneratedRuleCfg, Helper);
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)
117 if (Generated.tryCombineAll(Observer, MI, B))
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);
130 #define AARCH64PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_CPP
131 #include "AArch64GenPreLegalizeGICombiner.inc"
132 #undef AARCH64PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_CPP
137 class AArch64PreLegalizerCombiner : public MachineFunctionPass {
141 AArch64PreLegalizerCombiner(bool IsOptNone = false);
143 StringRef getPassName() const override { return "AArch64PreLegalizerCombiner"; }
145 bool runOnMachineFunction(MachineFunction &MF) override;
147 void getAnalysisUsage(AnalysisUsage &AU) const override;
151 } // end anonymous namespace
153 void AArch64PreLegalizerCombiner::getAnalysisUsage(AnalysisUsage &AU) const {
154 AU.addRequired<TargetPassConfig>();
155 AU.setPreservesCFG();
156 getSelectionDAGFallbackAnalysisUsage(AU);
157 AU.addRequired<GISelKnownBitsAnalysis>();
158 AU.addPreserved<GISelKnownBitsAnalysis>();
160 AU.addRequired<MachineDominatorTree>();
161 AU.addPreserved<MachineDominatorTree>();
163 MachineFunctionPass::getAnalysisUsage(AU);
166 AArch64PreLegalizerCombiner::AArch64PreLegalizerCombiner(bool IsOptNone)
167 : MachineFunctionPass(ID), IsOptNone(IsOptNone) {
168 initializeAArch64PreLegalizerCombinerPass(*PassRegistry::getPassRegistry());
171 bool AArch64PreLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) {
172 if (MF.getProperties().hasProperty(
173 MachineFunctionProperties::Property::FailedISel))
175 auto *TPC = &getAnalysis<TargetPassConfig>();
176 const Function &F = MF.getFunction();
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);
188 char AArch64PreLegalizerCombiner::ID = 0;
189 INITIALIZE_PASS_BEGIN(AArch64PreLegalizerCombiner, DEBUG_TYPE,
190 "Combine AArch64 machine instrs before legalization",
192 INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
193 INITIALIZE_PASS_DEPENDENCY(GISelKnownBitsAnalysis)
194 INITIALIZE_PASS_END(AArch64PreLegalizerCombiner, DEBUG_TYPE,
195 "Combine AArch64 machine instrs before legalization", false,
200 FunctionPass *createAArch64PreLegalizeCombiner(bool IsOptNone) {
201 return new AArch64PreLegalizerCombiner(IsOptNone);
203 } // end namespace llvm