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 #define AARCH64PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_DEPS
31 #include "AArch64GenGICombiner.inc"
32 #undef AARCH64PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_DEPS
35 #define AARCH64PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_H
36 #include "AArch64GenGICombiner.inc"
37 #undef AARCH64PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_H
39 class AArch64PreLegalizerCombinerInfo
: public CombinerInfo
{
41 MachineDominatorTree
*MDT
;
44 AArch64GenPreLegalizerCombinerHelper Generated
;
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
),
51 if (!Generated
.parseCommandLineOption())
52 report_fatal_error("Invalid rule identifier");
55 virtual bool combine(GISelChangeObserver
&Observer
, MachineInstr
&MI
,
56 MachineIRBuilder
&B
) const override
;
59 bool AArch64PreLegalizerCombinerInfo::combine(GISelChangeObserver
&Observer
,
61 MachineIRBuilder
&B
) const {
62 CombinerHelper
Helper(Observer
, B
, KB
, MDT
);
64 switch (MI
.getOpcode()) {
65 case TargetOpcode::G_CONCAT_VECTORS
:
66 return Helper
.tryCombineConcatVectors(MI
);
67 case TargetOpcode::G_SHUFFLE_VECTOR
:
68 return Helper
.tryCombineShuffleVector(MI
);
69 case TargetOpcode::G_LOAD
:
70 case TargetOpcode::G_SEXTLOAD
:
71 case TargetOpcode::G_ZEXTLOAD
: {
73 Changed
|= Helper
.tryCombineExtendingLoads(MI
);
74 Changed
|= Helper
.tryCombineIndexedLoadStore(MI
);
77 case TargetOpcode::G_STORE
:
78 return Helper
.tryCombineIndexedLoadStore(MI
);
79 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS
:
80 switch (MI
.getIntrinsicID()) {
81 case Intrinsic::memcpy
:
82 case Intrinsic::memmove
:
83 case Intrinsic::memset
: {
84 // If we're at -O0 set a maxlen of 32 to inline, otherwise let the other
86 unsigned MaxLen
= EnableOpt
? 0 : 32;
87 // Try to inline memcpy type calls if optimizations are enabled.
88 return (!EnableMinSize
) ? Helper
.tryCombineMemCpyFamily(MI
, MaxLen
)
96 if (Generated
.tryCombineAll(Observer
, MI
, B
))
102 #define AARCH64PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_CPP
103 #include "AArch64GenGICombiner.inc"
104 #undef AARCH64PRELEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_CPP
109 class AArch64PreLegalizerCombiner
: public MachineFunctionPass
{
113 AArch64PreLegalizerCombiner(bool IsOptNone
= false);
115 StringRef
getPassName() const override
{ return "AArch64PreLegalizerCombiner"; }
117 bool runOnMachineFunction(MachineFunction
&MF
) override
;
119 void getAnalysisUsage(AnalysisUsage
&AU
) const override
;
123 } // end anonymous namespace
125 void AArch64PreLegalizerCombiner::getAnalysisUsage(AnalysisUsage
&AU
) const {
126 AU
.addRequired
<TargetPassConfig
>();
127 AU
.setPreservesCFG();
128 getSelectionDAGFallbackAnalysisUsage(AU
);
129 AU
.addRequired
<GISelKnownBitsAnalysis
>();
130 AU
.addPreserved
<GISelKnownBitsAnalysis
>();
132 AU
.addRequired
<MachineDominatorTree
>();
133 AU
.addPreserved
<MachineDominatorTree
>();
135 MachineFunctionPass::getAnalysisUsage(AU
);
138 AArch64PreLegalizerCombiner::AArch64PreLegalizerCombiner(bool IsOptNone
)
139 : MachineFunctionPass(ID
), IsOptNone(IsOptNone
) {
140 initializeAArch64PreLegalizerCombinerPass(*PassRegistry::getPassRegistry());
143 bool AArch64PreLegalizerCombiner::runOnMachineFunction(MachineFunction
&MF
) {
144 if (MF
.getProperties().hasProperty(
145 MachineFunctionProperties::Property::FailedISel
))
147 auto *TPC
= &getAnalysis
<TargetPassConfig
>();
148 const Function
&F
= MF
.getFunction();
150 MF
.getTarget().getOptLevel() != CodeGenOpt::None
&& !skipFunction(F
);
151 GISelKnownBits
*KB
= &getAnalysis
<GISelKnownBitsAnalysis
>().get(MF
);
152 MachineDominatorTree
*MDT
=
153 IsOptNone
? nullptr : &getAnalysis
<MachineDominatorTree
>();
154 AArch64PreLegalizerCombinerInfo
PCInfo(EnableOpt
, F
.hasOptSize(),
155 F
.hasMinSize(), KB
, MDT
);
156 Combiner
C(PCInfo
, TPC
);
157 return C
.combineMachineInstrs(MF
, /*CSEInfo*/ nullptr);
160 char AArch64PreLegalizerCombiner::ID
= 0;
161 INITIALIZE_PASS_BEGIN(AArch64PreLegalizerCombiner
, DEBUG_TYPE
,
162 "Combine AArch64 machine instrs before legalization",
164 INITIALIZE_PASS_DEPENDENCY(TargetPassConfig
)
165 INITIALIZE_PASS_DEPENDENCY(GISelKnownBitsAnalysis
)
166 INITIALIZE_PASS_END(AArch64PreLegalizerCombiner
, DEBUG_TYPE
,
167 "Combine AArch64 machine instrs before legalization", false,
172 FunctionPass
*createAArch64PreLegalizeCombiner(bool IsOptNone
) {
173 return new AArch64PreLegalizerCombiner(IsOptNone
);
175 } // end namespace llvm