1//===--------------- X86PostLegalizerCombiner.cpp ---------------*- C++ -*-===//
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/// \file
10/// Post-legalization combines on generic MachineInstrs.
11///
12/// The combines here must preserve instruction legality.
13///
14/// Lowering combines (e.g. pseudo matching) should be handled by
15/// X86PostLegalizerLowering.
16///
17/// Combines which don't rely on instruction legality should go in the
18/// X86PreLegalizerCombiner.
19///
20//===----------------------------------------------------------------------===//
21#include "X86.h"
22#include "X86TargetMachine.h"
23#include "llvm/ADT/STLExtras.h"
24#include "llvm/CodeGen/GlobalISel/CSEInfo.h"
25#include "llvm/CodeGen/GlobalISel/CSEMIRBuilder.h"
26#include "llvm/CodeGen/GlobalISel/Combiner.h"
27#include "llvm/CodeGen/GlobalISel/CombinerHelper.h"
28#include "llvm/CodeGen/GlobalISel/CombinerInfo.h"
29#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"
30#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
31#include "llvm/CodeGen/GlobalISel/GISelValueTracking.h"
32#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
33#include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
34#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
35#include "llvm/CodeGen/GlobalISel/Utils.h"
36#include "llvm/CodeGen/MachineDominators.h"
37#include "llvm/CodeGen/MachineFunctionPass.h"
38#include "llvm/CodeGen/MachineRegisterInfo.h"
39#include "llvm/CodeGen/TargetOpcodes.h"
40#include "llvm/CodeGen/TargetPassConfig.h"
41#include "llvm/Support/Debug.h"
42
43#define GET_GICOMBINER_DEPS
44#include "X86GenPostLegalizeGICombiner.inc"
45#undef GET_GICOMBINER_DEPS
46
47#define DEBUG_TYPE "X86-postlegalizer-combiner"
48
49using namespace llvm;
50using namespace MIPatternMatch;
51
52namespace {
53
54#define GET_GICOMBINER_TYPES
55#include "X86GenPostLegalizeGICombiner.inc"
56#undef GET_GICOMBINER_TYPES
57
58class X86PostLegalizerCombinerImpl : public Combiner {
59protected:
60 const CombinerHelper Helper;
61 const X86PostLegalizerCombinerImplRuleConfig &RuleConfig;
62 const X86Subtarget &STI;
63
64public:
65 X86PostLegalizerCombinerImpl(
66 MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC,
67 GISelValueTracking &VT, GISelCSEInfo *CSEInfo,
68 const X86PostLegalizerCombinerImplRuleConfig &RuleConfig,
69 const X86Subtarget &STI, MachineDominatorTree *MDT,
70 const LegalizerInfo *LI);
71
72 static const char *getName() { return "X86PostLegalizerCombiner"; }
73
74 bool tryCombineAll(MachineInstr &I) const override;
75 bool tryCombineAllImpl(MachineInstr &I) const;
76
77private:
78#define GET_GICOMBINER_CLASS_MEMBERS
79#include "X86GenPostLegalizeGICombiner.inc"
80#undef GET_GICOMBINER_CLASS_MEMBERS
81};
82
83#define GET_GICOMBINER_IMPL
84#include "X86GenPostLegalizeGICombiner.inc"
85#undef GET_GICOMBINER_IMPL
86
87X86PostLegalizerCombinerImpl::X86PostLegalizerCombinerImpl(
88 MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC,
89 GISelValueTracking &VT, GISelCSEInfo *CSEInfo,
90 const X86PostLegalizerCombinerImplRuleConfig &RuleConfig,
91 const X86Subtarget &STI, MachineDominatorTree *MDT, const LegalizerInfo *LI)
92 : Combiner(MF, CInfo, TPC, &VT, CSEInfo),
93 Helper(Observer, B, /*IsPreLegalize=*/false, &VT, MDT, LI),
94 RuleConfig(RuleConfig), STI(STI),
95#define GET_GICOMBINER_CONSTRUCTOR_INITS
96#include "X86GenPostLegalizeGICombiner.inc"
97#undef GET_GICOMBINER_CONSTRUCTOR_INITS
98{
99}
100
101bool X86PostLegalizerCombinerImpl::tryCombineAll(MachineInstr &MI) const {
102 return tryCombineAllImpl(I&: MI);
103}
104
105class X86PostLegalizerCombiner : public MachineFunctionPass {
106public:
107 static char ID;
108
109 X86PostLegalizerCombiner();
110
111 StringRef getPassName() const override { return "X86PostLegalizerCombiner"; }
112
113 bool runOnMachineFunction(MachineFunction &MF) override;
114 void getAnalysisUsage(AnalysisUsage &AU) const override;
115
116private:
117 X86PostLegalizerCombinerImplRuleConfig RuleConfig;
118};
119} // end anonymous namespace
120
121void X86PostLegalizerCombiner::getAnalysisUsage(AnalysisUsage &AU) const {
122 AU.addRequired<TargetPassConfig>();
123 AU.setPreservesCFG();
124 getSelectionDAGFallbackAnalysisUsage(AU);
125 AU.addRequired<GISelValueTrackingAnalysisLegacy>();
126 AU.addPreserved<GISelValueTrackingAnalysisLegacy>();
127 // This is only added when processing level is not OptNone.
128 AU.addRequired<MachineDominatorTreeWrapperPass>();
129 AU.addPreserved<MachineDominatorTreeWrapperPass>();
130 AU.addRequired<GISelCSEAnalysisWrapperPass>();
131 AU.addPreserved<GISelCSEAnalysisWrapperPass>();
132
133 MachineFunctionPass::getAnalysisUsage(AU);
134}
135
136X86PostLegalizerCombiner::X86PostLegalizerCombiner() : MachineFunctionPass(ID) {
137 if (!RuleConfig.parseCommandLineOption())
138 reportFatalInternalError(reason: "Invalid rule identifier");
139}
140
141bool X86PostLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) {
142 if (MF.getProperties().hasFailedISel())
143 return false;
144 assert(MF.getProperties().hasLegalized() && "Expected a legalized function?");
145 auto *TPC = &getAnalysis<TargetPassConfig>();
146 const Function &F = MF.getFunction();
147
148 const X86Subtarget &ST = MF.getSubtarget<X86Subtarget>();
149 const auto *LI = ST.getLegalizerInfo();
150
151 GISelValueTracking *VT =
152 &getAnalysis<GISelValueTrackingAnalysisLegacy>().get(MF);
153 MachineDominatorTree *MDT =
154 &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
155 GISelCSEAnalysisWrapper &Wrapper =
156 getAnalysis<GISelCSEAnalysisWrapperPass>().getCSEWrapper();
157 auto *CSEInfo = &Wrapper.get(CSEOpt: TPC->getCSEConfig());
158
159 CombinerInfo CInfo(/*AllowIllegalOps=*/true,
160 /*ShouldLegalizeIllegal=*/false,
161 /*LegalizerInfo=*/nullptr, !skipFunction(F),
162 F.hasOptSize(), F.hasMinSize());
163 // Disable fixed-point iteration to reduce compile-time
164 CInfo.MaxIterations = 1;
165 CInfo.ObserverLvl = CombinerInfo::ObserverLevel::SinglePass;
166 // Legalizer performs DCE, so a full DCE pass is unnecessary.
167 CInfo.EnableFullDCE = false;
168 X86PostLegalizerCombinerImpl Impl(MF, CInfo, TPC, *VT, CSEInfo, RuleConfig,
169 ST, MDT, LI);
170 return Impl.combineMachineInstrs();
171}
172
173char X86PostLegalizerCombiner::ID = 0;
174INITIALIZE_PASS_BEGIN(X86PostLegalizerCombiner, DEBUG_TYPE,
175 "Combine X86 MachineInstrs after legalization", false,
176 false)
177INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
178INITIALIZE_PASS_DEPENDENCY(GISelValueTrackingAnalysisLegacy)
179INITIALIZE_PASS_END(X86PostLegalizerCombiner, DEBUG_TYPE,
180 "Combine X86 MachineInstrs after legalization", false,
181 false)
182
183namespace llvm {
184FunctionPass *createX86PostLegalizerCombiner() {
185 return new X86PostLegalizerCombiner();
186}
187} // end namespace llvm
188