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_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 #define AARCH64PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_DEPS
57 #include "AArch64GenGICombiner.inc"
58 #undef AARCH64PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_DEPS
61 #define AARCH64PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_H
62 #include "AArch64GenGICombiner.inc"
63 #undef AARCH64PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_H
65 class AArch64PreLegalizerCombinerInfo
: public CombinerInfo
{
67 MachineDominatorTree
*MDT
;
70 AArch64GenPreLegalizerCombinerHelper Generated
;
72 AArch64PreLegalizerCombinerInfo(bool EnableOpt
, bool OptSize
, bool MinSize
,
73 GISelKnownBits
*KB
, MachineDominatorTree
*MDT
)
74 : CombinerInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false,
75 /*LegalizerInfo*/ nullptr, EnableOpt
, OptSize
, MinSize
),
77 if (!Generated
.parseCommandLineOption())
78 report_fatal_error("Invalid rule identifier");
81 virtual bool combine(GISelChangeObserver
&Observer
, MachineInstr
&MI
,
82 MachineIRBuilder
&B
) const override
;
85 bool AArch64PreLegalizerCombinerInfo::combine(GISelChangeObserver
&Observer
,
87 MachineIRBuilder
&B
) const {
88 CombinerHelper
Helper(Observer
, B
, KB
, MDT
);
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
98 unsigned MaxLen
= EnableOpt
? 0 : 32;
99 // Try to inline memcpy type calls if optimizations are enabled.
100 return (!EnableMinSize
) ? Helper
.tryCombineMemCpyFamily(MI
, MaxLen
)
108 if (Generated
.tryCombineAll(Observer
, MI
, B
, Helper
))
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
);
121 #define AARCH64PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_CPP
122 #include "AArch64GenGICombiner.inc"
123 #undef AARCH64PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_CPP
128 class AArch64PreLegalizerCombiner
: public MachineFunctionPass
{
132 AArch64PreLegalizerCombiner(bool IsOptNone
= false);
134 StringRef
getPassName() const override
{ return "AArch64PreLegalizerCombiner"; }
136 bool runOnMachineFunction(MachineFunction
&MF
) override
;
138 void getAnalysisUsage(AnalysisUsage
&AU
) const override
;
142 } // end anonymous namespace
144 void AArch64PreLegalizerCombiner::getAnalysisUsage(AnalysisUsage
&AU
) const {
145 AU
.addRequired
<TargetPassConfig
>();
146 AU
.setPreservesCFG();
147 getSelectionDAGFallbackAnalysisUsage(AU
);
148 AU
.addRequired
<GISelKnownBitsAnalysis
>();
149 AU
.addPreserved
<GISelKnownBitsAnalysis
>();
151 AU
.addRequired
<MachineDominatorTree
>();
152 AU
.addPreserved
<MachineDominatorTree
>();
154 MachineFunctionPass::getAnalysisUsage(AU
);
157 AArch64PreLegalizerCombiner::AArch64PreLegalizerCombiner(bool IsOptNone
)
158 : MachineFunctionPass(ID
), IsOptNone(IsOptNone
) {
159 initializeAArch64PreLegalizerCombinerPass(*PassRegistry::getPassRegistry());
162 bool AArch64PreLegalizerCombiner::runOnMachineFunction(MachineFunction
&MF
) {
163 if (MF
.getProperties().hasProperty(
164 MachineFunctionProperties::Property::FailedISel
))
166 auto *TPC
= &getAnalysis
<TargetPassConfig
>();
167 const Function
&F
= MF
.getFunction();
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);
179 char AArch64PreLegalizerCombiner::ID
= 0;
180 INITIALIZE_PASS_BEGIN(AArch64PreLegalizerCombiner
, DEBUG_TYPE
,
181 "Combine AArch64 machine instrs before legalization",
183 INITIALIZE_PASS_DEPENDENCY(TargetPassConfig
)
184 INITIALIZE_PASS_DEPENDENCY(GISelKnownBitsAnalysis
)
185 INITIALIZE_PASS_END(AArch64PreLegalizerCombiner
, DEBUG_TYPE
,
186 "Combine AArch64 machine instrs before legalization", false,
191 FunctionPass
*createAArch64PreLegalizeCombiner(bool IsOptNone
) {
192 return new AArch64PreLegalizerCombiner(IsOptNone
);
194 } // end namespace llvm