1fee41517SMatt Arsenault //=== lib/CodeGen/GlobalISel/AMDGPUPostLegalizerCombiner.cpp ---------------===//
2fee41517SMatt Arsenault //
3fee41517SMatt Arsenault // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fee41517SMatt Arsenault // See https://llvm.org/LICENSE.txt for license information.
5fee41517SMatt Arsenault // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fee41517SMatt Arsenault //
7fee41517SMatt Arsenault //===----------------------------------------------------------------------===//
8fee41517SMatt Arsenault //
9fee41517SMatt Arsenault // This pass does combining of machine instructions at the generic MI level,
10fee41517SMatt Arsenault // after the legalizer.
11fee41517SMatt Arsenault //
12fee41517SMatt Arsenault //===----------------------------------------------------------------------===//
13fee41517SMatt Arsenault 
14fee41517SMatt Arsenault #include "AMDGPUTargetMachine.h"
15fee41517SMatt Arsenault #include "AMDGPULegalizerInfo.h"
16fee41517SMatt Arsenault #include "llvm/CodeGen/GlobalISel/Combiner.h"
17fee41517SMatt Arsenault #include "llvm/CodeGen/GlobalISel/CombinerHelper.h"
18fee41517SMatt Arsenault #include "llvm/CodeGen/GlobalISel/CombinerInfo.h"
19fee41517SMatt Arsenault #include "llvm/CodeGen/GlobalISel/GISelKnownBits.h"
20fee41517SMatt Arsenault #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
21fee41517SMatt Arsenault #include "llvm/CodeGen/MachineDominators.h"
22fee41517SMatt Arsenault #include "llvm/CodeGen/MachineFunctionPass.h"
23fee41517SMatt Arsenault #include "llvm/CodeGen/TargetPassConfig.h"
24fee41517SMatt Arsenault #include "llvm/Support/Debug.h"
25fee41517SMatt Arsenault #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
26fee41517SMatt Arsenault 
27fee41517SMatt Arsenault #define DEBUG_TYPE "amdgpu-postlegalizer-combiner"
28fee41517SMatt Arsenault 
29fee41517SMatt Arsenault using namespace llvm;
30fee41517SMatt Arsenault using namespace MIPatternMatch;
31fee41517SMatt Arsenault 
32fee41517SMatt Arsenault struct FMinFMaxLegacyInfo {
33fee41517SMatt Arsenault   Register LHS;
34fee41517SMatt Arsenault   Register RHS;
35fee41517SMatt Arsenault   Register True;
36fee41517SMatt Arsenault   Register False;
37fee41517SMatt Arsenault   CmpInst::Predicate Pred;
38fee41517SMatt Arsenault };
39fee41517SMatt Arsenault 
40fee41517SMatt Arsenault // TODO: Make sure fmin_legacy/fmax_legacy don't canonicalize
41fee41517SMatt Arsenault static bool matchFMinFMaxLegacy(MachineInstr &MI, MachineRegisterInfo &MRI,
42fee41517SMatt Arsenault                                 MachineFunction &MF, FMinFMaxLegacyInfo &Info) {
43fee41517SMatt Arsenault   // FIXME: Combines should have subtarget predicates, and we shouldn't need
44fee41517SMatt Arsenault   // this here.
45fee41517SMatt Arsenault   if (!MF.getSubtarget<GCNSubtarget>().hasFminFmaxLegacy())
46fee41517SMatt Arsenault     return false;
47fee41517SMatt Arsenault 
48fee41517SMatt Arsenault   // FIXME: Type predicate on pattern
49fee41517SMatt Arsenault   if (MRI.getType(MI.getOperand(0).getReg()) != LLT::scalar(32))
50fee41517SMatt Arsenault     return false;
51fee41517SMatt Arsenault 
52fee41517SMatt Arsenault   Register Cond = MI.getOperand(1).getReg();
53fee41517SMatt Arsenault   if (!MRI.hasOneNonDBGUse(Cond) ||
54fee41517SMatt Arsenault       !mi_match(Cond, MRI,
55fee41517SMatt Arsenault                 m_GFCmp(m_Pred(Info.Pred), m_Reg(Info.LHS), m_Reg(Info.RHS))))
56fee41517SMatt Arsenault     return false;
57fee41517SMatt Arsenault 
58fee41517SMatt Arsenault   Info.True = MI.getOperand(2).getReg();
59fee41517SMatt Arsenault   Info.False = MI.getOperand(3).getReg();
60fee41517SMatt Arsenault 
61fee41517SMatt Arsenault   if (!(Info.LHS == Info.True && Info.RHS == Info.False) &&
62fee41517SMatt Arsenault       !(Info.LHS == Info.False && Info.RHS == Info.True))
63fee41517SMatt Arsenault     return false;
64fee41517SMatt Arsenault 
65fee41517SMatt Arsenault   switch (Info.Pred) {
66fee41517SMatt Arsenault   case CmpInst::FCMP_FALSE:
67fee41517SMatt Arsenault   case CmpInst::FCMP_OEQ:
68fee41517SMatt Arsenault   case CmpInst::FCMP_ONE:
69fee41517SMatt Arsenault   case CmpInst::FCMP_ORD:
70fee41517SMatt Arsenault   case CmpInst::FCMP_UNO:
71fee41517SMatt Arsenault   case CmpInst::FCMP_UEQ:
72fee41517SMatt Arsenault   case CmpInst::FCMP_UNE:
73fee41517SMatt Arsenault   case CmpInst::FCMP_TRUE:
74fee41517SMatt Arsenault     return false;
75fee41517SMatt Arsenault   default:
76fee41517SMatt Arsenault     return true;
77fee41517SMatt Arsenault   }
78fee41517SMatt Arsenault }
79fee41517SMatt Arsenault 
80fee41517SMatt Arsenault static void applySelectFCmpToFMinToFMaxLegacy(MachineInstr &MI,
81fee41517SMatt Arsenault                                               const FMinFMaxLegacyInfo &Info) {
82fee41517SMatt Arsenault 
83fee41517SMatt Arsenault   auto buildNewInst = [&MI](unsigned Opc, Register X, Register Y) {
84fee41517SMatt Arsenault     MachineIRBuilder MIB(MI);
85fee41517SMatt Arsenault     MIB.buildInstr(Opc, {MI.getOperand(0)}, {X, Y}, MI.getFlags());
86fee41517SMatt Arsenault   };
87fee41517SMatt Arsenault 
88fee41517SMatt Arsenault   switch (Info.Pred) {
89fee41517SMatt Arsenault   case CmpInst::FCMP_ULT:
90fee41517SMatt Arsenault   case CmpInst::FCMP_ULE:
91fee41517SMatt Arsenault     if (Info.LHS == Info.True)
92fee41517SMatt Arsenault       buildNewInst(AMDGPU::G_AMDGPU_FMIN_LEGACY, Info.RHS, Info.LHS);
93fee41517SMatt Arsenault     else
94fee41517SMatt Arsenault       buildNewInst(AMDGPU::G_AMDGPU_FMAX_LEGACY, Info.LHS, Info.RHS);
95fee41517SMatt Arsenault     break;
96fee41517SMatt Arsenault   case CmpInst::FCMP_OLE:
97fee41517SMatt Arsenault   case CmpInst::FCMP_OLT: {
98fee41517SMatt Arsenault     // We need to permute the operands to get the correct NaN behavior. The
99fee41517SMatt Arsenault     // selected operand is the second one based on the failing compare with NaN,
100fee41517SMatt Arsenault     // so permute it based on the compare type the hardware uses.
101fee41517SMatt Arsenault     if (Info.LHS == Info.True)
102fee41517SMatt Arsenault       buildNewInst(AMDGPU::G_AMDGPU_FMIN_LEGACY, Info.LHS, Info.RHS);
103fee41517SMatt Arsenault     else
104fee41517SMatt Arsenault       buildNewInst(AMDGPU::G_AMDGPU_FMAX_LEGACY, Info.RHS, Info.LHS);
105fee41517SMatt Arsenault     break;
106fee41517SMatt Arsenault   }
107fee41517SMatt Arsenault   case CmpInst::FCMP_UGE:
108fee41517SMatt Arsenault   case CmpInst::FCMP_UGT: {
109fee41517SMatt Arsenault     if (Info.LHS == Info.True)
110fee41517SMatt Arsenault       buildNewInst(AMDGPU::G_AMDGPU_FMAX_LEGACY, Info.RHS, Info.LHS);
111fee41517SMatt Arsenault     else
112fee41517SMatt Arsenault       buildNewInst(AMDGPU::G_AMDGPU_FMIN_LEGACY, Info.LHS, Info.RHS);
113fee41517SMatt Arsenault     break;
114fee41517SMatt Arsenault   }
115fee41517SMatt Arsenault   case CmpInst::FCMP_OGT:
116fee41517SMatt Arsenault   case CmpInst::FCMP_OGE: {
117fee41517SMatt Arsenault     if (Info.LHS == Info.True)
118fee41517SMatt Arsenault       buildNewInst(AMDGPU::G_AMDGPU_FMAX_LEGACY, Info.LHS, Info.RHS);
119fee41517SMatt Arsenault     else
120fee41517SMatt Arsenault       buildNewInst(AMDGPU::G_AMDGPU_FMIN_LEGACY, Info.RHS, Info.LHS);
121fee41517SMatt Arsenault     break;
122fee41517SMatt Arsenault   }
123fee41517SMatt Arsenault   default:
124fee41517SMatt Arsenault     llvm_unreachable("predicate should not have matched");
125fee41517SMatt Arsenault   }
126fee41517SMatt Arsenault 
127fee41517SMatt Arsenault   MI.eraseFromParent();
128fee41517SMatt Arsenault }
129fee41517SMatt Arsenault 
130b27d255eSMatt Arsenault static bool matchUCharToFloat(MachineInstr &MI, MachineRegisterInfo &MRI,
131b27d255eSMatt Arsenault                               MachineFunction &MF, CombinerHelper &Helper) {
132b27d255eSMatt Arsenault   Register DstReg = MI.getOperand(0).getReg();
133b27d255eSMatt Arsenault 
134b27d255eSMatt Arsenault   // TODO: We could try to match extracting the higher bytes, which would be
135b27d255eSMatt Arsenault   // easier if i8 vectors weren't promoted to i32 vectors, particularly after
136b27d255eSMatt Arsenault   // types are legalized. v4i8 -> v4f32 is probably the only case to worry
137b27d255eSMatt Arsenault   // about in practice.
138b27d255eSMatt Arsenault   LLT Ty = MRI.getType(DstReg);
139b27d255eSMatt Arsenault   if (Ty == LLT::scalar(32) || Ty == LLT::scalar(16)) {
140db777eaeSMatt Arsenault     Register SrcReg = MI.getOperand(1).getReg();
141db777eaeSMatt Arsenault     unsigned SrcSize = MRI.getType(SrcReg).getSizeInBits();
142db777eaeSMatt Arsenault     assert(SrcSize == 16 || SrcSize == 32 || SrcSize == 64);
143db777eaeSMatt Arsenault     const APInt Mask = APInt::getHighBitsSet(SrcSize, SrcSize - 8);
144db777eaeSMatt Arsenault     return Helper.getKnownBits()->maskedValueIsZero(SrcReg, Mask);
145b27d255eSMatt Arsenault   }
146b27d255eSMatt Arsenault 
147b27d255eSMatt Arsenault   return false;
148b27d255eSMatt Arsenault }
149b27d255eSMatt Arsenault 
150b27d255eSMatt Arsenault static void applyUCharToFloat(MachineInstr &MI) {
151b27d255eSMatt Arsenault   MachineIRBuilder B(MI);
152b27d255eSMatt Arsenault 
153b27d255eSMatt Arsenault   const LLT S32 = LLT::scalar(32);
154b27d255eSMatt Arsenault 
155b27d255eSMatt Arsenault   Register DstReg = MI.getOperand(0).getReg();
156db777eaeSMatt Arsenault   Register SrcReg = MI.getOperand(1).getReg();
157b27d255eSMatt Arsenault   LLT Ty = B.getMRI()->getType(DstReg);
158db777eaeSMatt Arsenault   LLT SrcTy = B.getMRI()->getType(SrcReg);
159db777eaeSMatt Arsenault   if (SrcTy != S32)
160db777eaeSMatt Arsenault     SrcReg = B.buildAnyExtOrTrunc(S32, SrcReg).getReg(0);
161b27d255eSMatt Arsenault 
162b27d255eSMatt Arsenault   if (Ty == S32) {
163b27d255eSMatt Arsenault     B.buildInstr(AMDGPU::G_AMDGPU_CVT_F32_UBYTE0, {DstReg},
164db777eaeSMatt Arsenault                    {SrcReg}, MI.getFlags());
165b27d255eSMatt Arsenault   } else {
166b27d255eSMatt Arsenault     auto Cvt0 = B.buildInstr(AMDGPU::G_AMDGPU_CVT_F32_UBYTE0, {S32},
167db777eaeSMatt Arsenault                              {SrcReg}, MI.getFlags());
168b27d255eSMatt Arsenault     B.buildFPTrunc(DstReg, Cvt0, MI.getFlags());
169b27d255eSMatt Arsenault   }
170b27d255eSMatt Arsenault 
171b27d255eSMatt Arsenault   MI.eraseFromParent();
172b27d255eSMatt Arsenault }
173fee41517SMatt Arsenault 
1740ba40d4cSMatt Arsenault // FIXME: Should be able to have 2 separate matchdatas rather than custom struct
1750ba40d4cSMatt Arsenault // boilerplate.
1760ba40d4cSMatt Arsenault struct CvtF32UByteMatchInfo {
1770ba40d4cSMatt Arsenault   Register CvtVal;
1780ba40d4cSMatt Arsenault   unsigned ShiftOffset;
1790ba40d4cSMatt Arsenault };
1800ba40d4cSMatt Arsenault 
1810ba40d4cSMatt Arsenault static bool matchCvtF32UByteN(MachineInstr &MI, MachineRegisterInfo &MRI,
1820ba40d4cSMatt Arsenault                               MachineFunction &MF,
1830ba40d4cSMatt Arsenault                               CvtF32UByteMatchInfo &MatchInfo) {
1840ba40d4cSMatt Arsenault   Register SrcReg = MI.getOperand(1).getReg();
1850ba40d4cSMatt Arsenault 
1860ba40d4cSMatt Arsenault   // Look through G_ZEXT.
1870ba40d4cSMatt Arsenault   mi_match(SrcReg, MRI, m_GZExt(m_Reg(SrcReg)));
1880ba40d4cSMatt Arsenault 
1890ba40d4cSMatt Arsenault   Register Src0;
1900ba40d4cSMatt Arsenault   int64_t ShiftAmt;
1910ba40d4cSMatt Arsenault   bool IsShr = mi_match(SrcReg, MRI, m_GLShr(m_Reg(Src0), m_ICst(ShiftAmt)));
1920ba40d4cSMatt Arsenault   if (IsShr || mi_match(SrcReg, MRI, m_GShl(m_Reg(Src0), m_ICst(ShiftAmt)))) {
1930ba40d4cSMatt Arsenault     const unsigned Offset = MI.getOpcode() - AMDGPU::G_AMDGPU_CVT_F32_UBYTE0;
1940ba40d4cSMatt Arsenault 
1950ba40d4cSMatt Arsenault     unsigned ShiftOffset = 8 * Offset;
1960ba40d4cSMatt Arsenault     if (IsShr)
1970ba40d4cSMatt Arsenault       ShiftOffset += ShiftAmt;
1980ba40d4cSMatt Arsenault     else
1990ba40d4cSMatt Arsenault       ShiftOffset -= ShiftAmt;
2000ba40d4cSMatt Arsenault 
2010ba40d4cSMatt Arsenault     MatchInfo.CvtVal = Src0;
2020ba40d4cSMatt Arsenault     MatchInfo.ShiftOffset = ShiftOffset;
2030ba40d4cSMatt Arsenault     return ShiftOffset < 32 && ShiftOffset >= 8 && (ShiftOffset % 8) == 0;
2040ba40d4cSMatt Arsenault   }
2050ba40d4cSMatt Arsenault 
2060ba40d4cSMatt Arsenault   // TODO: Simplify demanded bits.
2070ba40d4cSMatt Arsenault   return false;
2080ba40d4cSMatt Arsenault }
2090ba40d4cSMatt Arsenault 
2100ba40d4cSMatt Arsenault static void applyCvtF32UByteN(MachineInstr &MI,
2110ba40d4cSMatt Arsenault                               const CvtF32UByteMatchInfo &MatchInfo) {
2120ba40d4cSMatt Arsenault   MachineIRBuilder B(MI);
2130ba40d4cSMatt Arsenault   unsigned NewOpc = AMDGPU::G_AMDGPU_CVT_F32_UBYTE0 + MatchInfo.ShiftOffset / 8;
2140ba40d4cSMatt Arsenault 
2150ba40d4cSMatt Arsenault   const LLT S32 = LLT::scalar(32);
2160ba40d4cSMatt Arsenault   Register CvtSrc = MatchInfo.CvtVal;
2170ba40d4cSMatt Arsenault   LLT SrcTy = B.getMRI()->getType(MatchInfo.CvtVal);
2180ba40d4cSMatt Arsenault   if (SrcTy != S32) {
2190ba40d4cSMatt Arsenault     assert(SrcTy.isScalar() && SrcTy.getSizeInBits() >= 8);
2200ba40d4cSMatt Arsenault     CvtSrc = B.buildAnyExt(S32, CvtSrc).getReg(0);
2210ba40d4cSMatt Arsenault   }
2220ba40d4cSMatt Arsenault 
2230ba40d4cSMatt Arsenault   assert(MI.getOpcode() != NewOpc);
2240ba40d4cSMatt Arsenault   B.buildInstr(NewOpc, {MI.getOperand(0)}, {CvtSrc}, MI.getFlags());
2250ba40d4cSMatt Arsenault   MI.eraseFromParent();
2260ba40d4cSMatt Arsenault }
2270ba40d4cSMatt Arsenault 
228fee41517SMatt Arsenault #define AMDGPUPOSTLEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_DEPS
229fee41517SMatt Arsenault #include "AMDGPUGenPostLegalizeGICombiner.inc"
230fee41517SMatt Arsenault #undef AMDGPUPOSTLEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_DEPS
231fee41517SMatt Arsenault 
232fee41517SMatt Arsenault namespace {
233fee41517SMatt Arsenault #define AMDGPUPOSTLEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_H
234fee41517SMatt Arsenault #include "AMDGPUGenPostLegalizeGICombiner.inc"
235fee41517SMatt Arsenault #undef AMDGPUPOSTLEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_H
236fee41517SMatt Arsenault 
23716bcd545SMatt Arsenault class AMDGPUPostLegalizerCombinerInfo final : public CombinerInfo {
238fee41517SMatt Arsenault   GISelKnownBits *KB;
239fee41517SMatt Arsenault   MachineDominatorTree *MDT;
240fee41517SMatt Arsenault 
241fee41517SMatt Arsenault public:
242e35ba099SDaniel Sanders   AMDGPUGenPostLegalizerCombinerHelperRuleConfig GeneratedRuleCfg;
243fee41517SMatt Arsenault 
244fee41517SMatt Arsenault   AMDGPUPostLegalizerCombinerInfo(bool EnableOpt, bool OptSize, bool MinSize,
245fee41517SMatt Arsenault                                   const AMDGPULegalizerInfo *LI,
246fee41517SMatt Arsenault                                   GISelKnownBits *KB, MachineDominatorTree *MDT)
247fee41517SMatt Arsenault       : CombinerInfo(/*AllowIllegalOps*/ false, /*ShouldLegalizeIllegal*/ true,
248fee41517SMatt Arsenault                      /*LegalizerInfo*/ LI, EnableOpt, OptSize, MinSize),
249fee41517SMatt Arsenault         KB(KB), MDT(MDT) {
250e35ba099SDaniel Sanders     if (!GeneratedRuleCfg.parseCommandLineOption())
251fee41517SMatt Arsenault       report_fatal_error("Invalid rule identifier");
252fee41517SMatt Arsenault   }
253fee41517SMatt Arsenault 
254d15723efSMatt Arsenault   bool combine(GISelChangeObserver &Observer, MachineInstr &MI,
255fee41517SMatt Arsenault                MachineIRBuilder &B) const override;
256fee41517SMatt Arsenault };
257fee41517SMatt Arsenault 
258fee41517SMatt Arsenault bool AMDGPUPostLegalizerCombinerInfo::combine(GISelChangeObserver &Observer,
259fee41517SMatt Arsenault                                               MachineInstr &MI,
260fee41517SMatt Arsenault                                               MachineIRBuilder &B) const {
261*66ffa0e9SMatt Arsenault   CombinerHelper Helper(Observer, B, KB, MDT, LInfo);
262e35ba099SDaniel Sanders   AMDGPUGenPostLegalizerCombinerHelper Generated(GeneratedRuleCfg);
263fee41517SMatt Arsenault 
264fee41517SMatt Arsenault   if (Generated.tryCombineAll(Observer, MI, B, Helper))
265fee41517SMatt Arsenault     return true;
266fee41517SMatt Arsenault 
267fee41517SMatt Arsenault   switch (MI.getOpcode()) {
268fee41517SMatt Arsenault   case TargetOpcode::G_SHL:
269fee41517SMatt Arsenault   case TargetOpcode::G_LSHR:
270fee41517SMatt Arsenault   case TargetOpcode::G_ASHR:
271fee41517SMatt Arsenault     // On some subtargets, 64-bit shift is a quarter rate instruction. In the
272fee41517SMatt Arsenault     // common case, splitting this into a move and a 32-bit shift is faster and
273fee41517SMatt Arsenault     // the same code size.
274fee41517SMatt Arsenault     return Helper.tryCombineShiftToUnmerge(MI, 32);
275fee41517SMatt Arsenault   }
276fee41517SMatt Arsenault 
277fee41517SMatt Arsenault   return false;
278fee41517SMatt Arsenault }
279fee41517SMatt Arsenault 
280fee41517SMatt Arsenault #define AMDGPUPOSTLEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_CPP
281fee41517SMatt Arsenault #include "AMDGPUGenPostLegalizeGICombiner.inc"
282fee41517SMatt Arsenault #undef AMDGPUPOSTLEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_CPP
283fee41517SMatt Arsenault 
284fee41517SMatt Arsenault // Pass boilerplate
285fee41517SMatt Arsenault // ================
286fee41517SMatt Arsenault 
287fee41517SMatt Arsenault class AMDGPUPostLegalizerCombiner : public MachineFunctionPass {
288fee41517SMatt Arsenault public:
289fee41517SMatt Arsenault   static char ID;
290fee41517SMatt Arsenault 
291fee41517SMatt Arsenault   AMDGPUPostLegalizerCombiner(bool IsOptNone = false);
292fee41517SMatt Arsenault 
293fee41517SMatt Arsenault   StringRef getPassName() const override {
294fee41517SMatt Arsenault     return "AMDGPUPostLegalizerCombiner";
295fee41517SMatt Arsenault   }
296fee41517SMatt Arsenault 
297fee41517SMatt Arsenault   bool runOnMachineFunction(MachineFunction &MF) override;
298fee41517SMatt Arsenault 
299fee41517SMatt Arsenault   void getAnalysisUsage(AnalysisUsage &AU) const override;
300fee41517SMatt Arsenault private:
301fee41517SMatt Arsenault   bool IsOptNone;
302fee41517SMatt Arsenault };
303fee41517SMatt Arsenault } // end anonymous namespace
304fee41517SMatt Arsenault 
305fee41517SMatt Arsenault void AMDGPUPostLegalizerCombiner::getAnalysisUsage(AnalysisUsage &AU) const {
306fee41517SMatt Arsenault   AU.addRequired<TargetPassConfig>();
307fee41517SMatt Arsenault   AU.setPreservesCFG();
308fee41517SMatt Arsenault   getSelectionDAGFallbackAnalysisUsage(AU);
309fee41517SMatt Arsenault   AU.addRequired<GISelKnownBitsAnalysis>();
310fee41517SMatt Arsenault   AU.addPreserved<GISelKnownBitsAnalysis>();
311fee41517SMatt Arsenault   if (!IsOptNone) {
312fee41517SMatt Arsenault     AU.addRequired<MachineDominatorTree>();
313fee41517SMatt Arsenault     AU.addPreserved<MachineDominatorTree>();
314fee41517SMatt Arsenault   }
315fee41517SMatt Arsenault   MachineFunctionPass::getAnalysisUsage(AU);
316fee41517SMatt Arsenault }
317fee41517SMatt Arsenault 
318fee41517SMatt Arsenault AMDGPUPostLegalizerCombiner::AMDGPUPostLegalizerCombiner(bool IsOptNone)
319fee41517SMatt Arsenault   : MachineFunctionPass(ID), IsOptNone(IsOptNone) {
320fee41517SMatt Arsenault   initializeAMDGPUPostLegalizerCombinerPass(*PassRegistry::getPassRegistry());
321fee41517SMatt Arsenault }
322fee41517SMatt Arsenault 
323fee41517SMatt Arsenault bool AMDGPUPostLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) {
324fee41517SMatt Arsenault   if (MF.getProperties().hasProperty(
325fee41517SMatt Arsenault           MachineFunctionProperties::Property::FailedISel))
326fee41517SMatt Arsenault     return false;
327fee41517SMatt Arsenault   auto *TPC = &getAnalysis<TargetPassConfig>();
328fee41517SMatt Arsenault   const Function &F = MF.getFunction();
329fee41517SMatt Arsenault   bool EnableOpt =
330fee41517SMatt Arsenault       MF.getTarget().getOptLevel() != CodeGenOpt::None && !skipFunction(F);
331fee41517SMatt Arsenault 
332fee41517SMatt Arsenault   const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
333fee41517SMatt Arsenault   const AMDGPULegalizerInfo *LI
334fee41517SMatt Arsenault     = static_cast<const AMDGPULegalizerInfo *>(ST.getLegalizerInfo());
335fee41517SMatt Arsenault 
336fee41517SMatt Arsenault   GISelKnownBits *KB = &getAnalysis<GISelKnownBitsAnalysis>().get(MF);
337fee41517SMatt Arsenault   MachineDominatorTree *MDT =
338fee41517SMatt Arsenault       IsOptNone ? nullptr : &getAnalysis<MachineDominatorTree>();
339fee41517SMatt Arsenault   AMDGPUPostLegalizerCombinerInfo PCInfo(EnableOpt, F.hasOptSize(),
340fee41517SMatt Arsenault                                          F.hasMinSize(), LI, KB, MDT);
341fee41517SMatt Arsenault   Combiner C(PCInfo, TPC);
342fee41517SMatt Arsenault   return C.combineMachineInstrs(MF, /*CSEInfo*/ nullptr);
343fee41517SMatt Arsenault }
344fee41517SMatt Arsenault 
345fee41517SMatt Arsenault char AMDGPUPostLegalizerCombiner::ID = 0;
346fee41517SMatt Arsenault INITIALIZE_PASS_BEGIN(AMDGPUPostLegalizerCombiner, DEBUG_TYPE,
347fee41517SMatt Arsenault                       "Combine AMDGPU machine instrs after legalization",
348fee41517SMatt Arsenault                       false, false)
349fee41517SMatt Arsenault INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
350fee41517SMatt Arsenault INITIALIZE_PASS_DEPENDENCY(GISelKnownBitsAnalysis)
351fee41517SMatt Arsenault INITIALIZE_PASS_END(AMDGPUPostLegalizerCombiner, DEBUG_TYPE,
352fee41517SMatt Arsenault                     "Combine AMDGPU machine instrs after legalization", false,
353fee41517SMatt Arsenault                     false)
354fee41517SMatt Arsenault 
355fee41517SMatt Arsenault namespace llvm {
356fee41517SMatt Arsenault FunctionPass *createAMDGPUPostLegalizeCombiner(bool IsOptNone) {
357fee41517SMatt Arsenault   return new AMDGPUPostLegalizerCombiner(IsOptNone);
358fee41517SMatt Arsenault }
359fee41517SMatt Arsenault } // end namespace llvm
360