15ffd83dbSDimitry Andric //=== lib/CodeGen/GlobalISel/AMDGPUPostLegalizerCombiner.cpp ---------------===//
25ffd83dbSDimitry Andric //
35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65ffd83dbSDimitry Andric //
75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
85ffd83dbSDimitry Andric //
95ffd83dbSDimitry Andric // This pass does combining of machine instructions at the generic MI level,
105ffd83dbSDimitry Andric // after the legalizer.
115ffd83dbSDimitry Andric //
125ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
135ffd83dbSDimitry Andric 
145ffd83dbSDimitry Andric #include "AMDGPUTargetMachine.h"
155ffd83dbSDimitry Andric #include "AMDGPULegalizerInfo.h"
165ffd83dbSDimitry Andric #include "llvm/CodeGen/GlobalISel/Combiner.h"
175ffd83dbSDimitry Andric #include "llvm/CodeGen/GlobalISel/CombinerHelper.h"
185ffd83dbSDimitry Andric #include "llvm/CodeGen/GlobalISel/CombinerInfo.h"
195ffd83dbSDimitry Andric #include "llvm/CodeGen/GlobalISel/GISelKnownBits.h"
205ffd83dbSDimitry Andric #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
215ffd83dbSDimitry Andric #include "llvm/CodeGen/MachineDominators.h"
225ffd83dbSDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
235ffd83dbSDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h"
245ffd83dbSDimitry Andric #include "llvm/Support/Debug.h"
255ffd83dbSDimitry Andric #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
265ffd83dbSDimitry Andric 
275ffd83dbSDimitry Andric #define DEBUG_TYPE "amdgpu-postlegalizer-combiner"
285ffd83dbSDimitry Andric 
295ffd83dbSDimitry Andric using namespace llvm;
305ffd83dbSDimitry Andric using namespace MIPatternMatch;
315ffd83dbSDimitry Andric 
325ffd83dbSDimitry Andric struct FMinFMaxLegacyInfo {
335ffd83dbSDimitry Andric   Register LHS;
345ffd83dbSDimitry Andric   Register RHS;
355ffd83dbSDimitry Andric   Register True;
365ffd83dbSDimitry Andric   Register False;
375ffd83dbSDimitry Andric   CmpInst::Predicate Pred;
385ffd83dbSDimitry Andric };
395ffd83dbSDimitry Andric 
405ffd83dbSDimitry Andric // TODO: Make sure fmin_legacy/fmax_legacy don't canonicalize
415ffd83dbSDimitry Andric static bool matchFMinFMaxLegacy(MachineInstr &MI, MachineRegisterInfo &MRI,
425ffd83dbSDimitry Andric                                 MachineFunction &MF, FMinFMaxLegacyInfo &Info) {
435ffd83dbSDimitry Andric   // FIXME: Combines should have subtarget predicates, and we shouldn't need
445ffd83dbSDimitry Andric   // this here.
455ffd83dbSDimitry Andric   if (!MF.getSubtarget<GCNSubtarget>().hasFminFmaxLegacy())
465ffd83dbSDimitry Andric     return false;
475ffd83dbSDimitry Andric 
485ffd83dbSDimitry Andric   // FIXME: Type predicate on pattern
495ffd83dbSDimitry Andric   if (MRI.getType(MI.getOperand(0).getReg()) != LLT::scalar(32))
505ffd83dbSDimitry Andric     return false;
515ffd83dbSDimitry Andric 
525ffd83dbSDimitry Andric   Register Cond = MI.getOperand(1).getReg();
535ffd83dbSDimitry Andric   if (!MRI.hasOneNonDBGUse(Cond) ||
545ffd83dbSDimitry Andric       !mi_match(Cond, MRI,
555ffd83dbSDimitry Andric                 m_GFCmp(m_Pred(Info.Pred), m_Reg(Info.LHS), m_Reg(Info.RHS))))
565ffd83dbSDimitry Andric     return false;
575ffd83dbSDimitry Andric 
585ffd83dbSDimitry Andric   Info.True = MI.getOperand(2).getReg();
595ffd83dbSDimitry Andric   Info.False = MI.getOperand(3).getReg();
605ffd83dbSDimitry Andric 
615ffd83dbSDimitry Andric   if (!(Info.LHS == Info.True && Info.RHS == Info.False) &&
625ffd83dbSDimitry Andric       !(Info.LHS == Info.False && Info.RHS == Info.True))
635ffd83dbSDimitry Andric     return false;
645ffd83dbSDimitry Andric 
655ffd83dbSDimitry Andric   switch (Info.Pred) {
665ffd83dbSDimitry Andric   case CmpInst::FCMP_FALSE:
675ffd83dbSDimitry Andric   case CmpInst::FCMP_OEQ:
685ffd83dbSDimitry Andric   case CmpInst::FCMP_ONE:
695ffd83dbSDimitry Andric   case CmpInst::FCMP_ORD:
705ffd83dbSDimitry Andric   case CmpInst::FCMP_UNO:
715ffd83dbSDimitry Andric   case CmpInst::FCMP_UEQ:
725ffd83dbSDimitry Andric   case CmpInst::FCMP_UNE:
735ffd83dbSDimitry Andric   case CmpInst::FCMP_TRUE:
745ffd83dbSDimitry Andric     return false;
755ffd83dbSDimitry Andric   default:
765ffd83dbSDimitry Andric     return true;
775ffd83dbSDimitry Andric   }
785ffd83dbSDimitry Andric }
795ffd83dbSDimitry Andric 
805ffd83dbSDimitry Andric static void applySelectFCmpToFMinToFMaxLegacy(MachineInstr &MI,
815ffd83dbSDimitry Andric                                               const FMinFMaxLegacyInfo &Info) {
825ffd83dbSDimitry Andric 
835ffd83dbSDimitry Andric   auto buildNewInst = [&MI](unsigned Opc, Register X, Register Y) {
845ffd83dbSDimitry Andric     MachineIRBuilder MIB(MI);
855ffd83dbSDimitry Andric     MIB.buildInstr(Opc, {MI.getOperand(0)}, {X, Y}, MI.getFlags());
865ffd83dbSDimitry Andric   };
875ffd83dbSDimitry Andric 
885ffd83dbSDimitry Andric   switch (Info.Pred) {
895ffd83dbSDimitry Andric   case CmpInst::FCMP_ULT:
905ffd83dbSDimitry Andric   case CmpInst::FCMP_ULE:
915ffd83dbSDimitry Andric     if (Info.LHS == Info.True)
925ffd83dbSDimitry Andric       buildNewInst(AMDGPU::G_AMDGPU_FMIN_LEGACY, Info.RHS, Info.LHS);
935ffd83dbSDimitry Andric     else
945ffd83dbSDimitry Andric       buildNewInst(AMDGPU::G_AMDGPU_FMAX_LEGACY, Info.LHS, Info.RHS);
955ffd83dbSDimitry Andric     break;
965ffd83dbSDimitry Andric   case CmpInst::FCMP_OLE:
975ffd83dbSDimitry Andric   case CmpInst::FCMP_OLT: {
985ffd83dbSDimitry Andric     // We need to permute the operands to get the correct NaN behavior. The
995ffd83dbSDimitry Andric     // selected operand is the second one based on the failing compare with NaN,
1005ffd83dbSDimitry Andric     // so permute it based on the compare type the hardware uses.
1015ffd83dbSDimitry Andric     if (Info.LHS == Info.True)
1025ffd83dbSDimitry Andric       buildNewInst(AMDGPU::G_AMDGPU_FMIN_LEGACY, Info.LHS, Info.RHS);
1035ffd83dbSDimitry Andric     else
1045ffd83dbSDimitry Andric       buildNewInst(AMDGPU::G_AMDGPU_FMAX_LEGACY, Info.RHS, Info.LHS);
1055ffd83dbSDimitry Andric     break;
1065ffd83dbSDimitry Andric   }
1075ffd83dbSDimitry Andric   case CmpInst::FCMP_UGE:
1085ffd83dbSDimitry Andric   case CmpInst::FCMP_UGT: {
1095ffd83dbSDimitry Andric     if (Info.LHS == Info.True)
1105ffd83dbSDimitry Andric       buildNewInst(AMDGPU::G_AMDGPU_FMAX_LEGACY, Info.RHS, Info.LHS);
1115ffd83dbSDimitry Andric     else
1125ffd83dbSDimitry Andric       buildNewInst(AMDGPU::G_AMDGPU_FMIN_LEGACY, Info.LHS, Info.RHS);
1135ffd83dbSDimitry Andric     break;
1145ffd83dbSDimitry Andric   }
1155ffd83dbSDimitry Andric   case CmpInst::FCMP_OGT:
1165ffd83dbSDimitry Andric   case CmpInst::FCMP_OGE: {
1175ffd83dbSDimitry Andric     if (Info.LHS == Info.True)
1185ffd83dbSDimitry Andric       buildNewInst(AMDGPU::G_AMDGPU_FMAX_LEGACY, Info.LHS, Info.RHS);
1195ffd83dbSDimitry Andric     else
1205ffd83dbSDimitry Andric       buildNewInst(AMDGPU::G_AMDGPU_FMIN_LEGACY, Info.RHS, Info.LHS);
1215ffd83dbSDimitry Andric     break;
1225ffd83dbSDimitry Andric   }
1235ffd83dbSDimitry Andric   default:
1245ffd83dbSDimitry Andric     llvm_unreachable("predicate should not have matched");
1255ffd83dbSDimitry Andric   }
1265ffd83dbSDimitry Andric 
1275ffd83dbSDimitry Andric   MI.eraseFromParent();
1285ffd83dbSDimitry Andric }
1295ffd83dbSDimitry Andric 
1305ffd83dbSDimitry Andric static bool matchUCharToFloat(MachineInstr &MI, MachineRegisterInfo &MRI,
1315ffd83dbSDimitry Andric                               MachineFunction &MF, CombinerHelper &Helper) {
1325ffd83dbSDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
1335ffd83dbSDimitry Andric 
1345ffd83dbSDimitry Andric   // TODO: We could try to match extracting the higher bytes, which would be
1355ffd83dbSDimitry Andric   // easier if i8 vectors weren't promoted to i32 vectors, particularly after
1365ffd83dbSDimitry Andric   // types are legalized. v4i8 -> v4f32 is probably the only case to worry
1375ffd83dbSDimitry Andric   // about in practice.
1385ffd83dbSDimitry Andric   LLT Ty = MRI.getType(DstReg);
1395ffd83dbSDimitry Andric   if (Ty == LLT::scalar(32) || Ty == LLT::scalar(16)) {
1405ffd83dbSDimitry Andric     Register SrcReg = MI.getOperand(1).getReg();
1415ffd83dbSDimitry Andric     unsigned SrcSize = MRI.getType(SrcReg).getSizeInBits();
1425ffd83dbSDimitry Andric     assert(SrcSize == 16 || SrcSize == 32 || SrcSize == 64);
1435ffd83dbSDimitry Andric     const APInt Mask = APInt::getHighBitsSet(SrcSize, SrcSize - 8);
1445ffd83dbSDimitry Andric     return Helper.getKnownBits()->maskedValueIsZero(SrcReg, Mask);
1455ffd83dbSDimitry Andric   }
1465ffd83dbSDimitry Andric 
1475ffd83dbSDimitry Andric   return false;
1485ffd83dbSDimitry Andric }
1495ffd83dbSDimitry Andric 
1505ffd83dbSDimitry Andric static void applyUCharToFloat(MachineInstr &MI) {
1515ffd83dbSDimitry Andric   MachineIRBuilder B(MI);
1525ffd83dbSDimitry Andric 
1535ffd83dbSDimitry Andric   const LLT S32 = LLT::scalar(32);
1545ffd83dbSDimitry Andric 
1555ffd83dbSDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
1565ffd83dbSDimitry Andric   Register SrcReg = MI.getOperand(1).getReg();
1575ffd83dbSDimitry Andric   LLT Ty = B.getMRI()->getType(DstReg);
1585ffd83dbSDimitry Andric   LLT SrcTy = B.getMRI()->getType(SrcReg);
1595ffd83dbSDimitry Andric   if (SrcTy != S32)
1605ffd83dbSDimitry Andric     SrcReg = B.buildAnyExtOrTrunc(S32, SrcReg).getReg(0);
1615ffd83dbSDimitry Andric 
1625ffd83dbSDimitry Andric   if (Ty == S32) {
1635ffd83dbSDimitry Andric     B.buildInstr(AMDGPU::G_AMDGPU_CVT_F32_UBYTE0, {DstReg},
1645ffd83dbSDimitry Andric                    {SrcReg}, MI.getFlags());
1655ffd83dbSDimitry Andric   } else {
1665ffd83dbSDimitry Andric     auto Cvt0 = B.buildInstr(AMDGPU::G_AMDGPU_CVT_F32_UBYTE0, {S32},
1675ffd83dbSDimitry Andric                              {SrcReg}, MI.getFlags());
1685ffd83dbSDimitry Andric     B.buildFPTrunc(DstReg, Cvt0, MI.getFlags());
1695ffd83dbSDimitry Andric   }
1705ffd83dbSDimitry Andric 
1715ffd83dbSDimitry Andric   MI.eraseFromParent();
1725ffd83dbSDimitry Andric }
1735ffd83dbSDimitry Andric 
1745ffd83dbSDimitry Andric // FIXME: Should be able to have 2 separate matchdatas rather than custom struct
1755ffd83dbSDimitry Andric // boilerplate.
1765ffd83dbSDimitry Andric struct CvtF32UByteMatchInfo {
1775ffd83dbSDimitry Andric   Register CvtVal;
1785ffd83dbSDimitry Andric   unsigned ShiftOffset;
1795ffd83dbSDimitry Andric };
1805ffd83dbSDimitry Andric 
1815ffd83dbSDimitry Andric static bool matchCvtF32UByteN(MachineInstr &MI, MachineRegisterInfo &MRI,
1825ffd83dbSDimitry Andric                               MachineFunction &MF,
1835ffd83dbSDimitry Andric                               CvtF32UByteMatchInfo &MatchInfo) {
1845ffd83dbSDimitry Andric   Register SrcReg = MI.getOperand(1).getReg();
1855ffd83dbSDimitry Andric 
1865ffd83dbSDimitry Andric   // Look through G_ZEXT.
1875ffd83dbSDimitry Andric   mi_match(SrcReg, MRI, m_GZExt(m_Reg(SrcReg)));
1885ffd83dbSDimitry Andric 
1895ffd83dbSDimitry Andric   Register Src0;
1905ffd83dbSDimitry Andric   int64_t ShiftAmt;
1915ffd83dbSDimitry Andric   bool IsShr = mi_match(SrcReg, MRI, m_GLShr(m_Reg(Src0), m_ICst(ShiftAmt)));
1925ffd83dbSDimitry Andric   if (IsShr || mi_match(SrcReg, MRI, m_GShl(m_Reg(Src0), m_ICst(ShiftAmt)))) {
1935ffd83dbSDimitry Andric     const unsigned Offset = MI.getOpcode() - AMDGPU::G_AMDGPU_CVT_F32_UBYTE0;
1945ffd83dbSDimitry Andric 
1955ffd83dbSDimitry Andric     unsigned ShiftOffset = 8 * Offset;
1965ffd83dbSDimitry Andric     if (IsShr)
1975ffd83dbSDimitry Andric       ShiftOffset += ShiftAmt;
1985ffd83dbSDimitry Andric     else
1995ffd83dbSDimitry Andric       ShiftOffset -= ShiftAmt;
2005ffd83dbSDimitry Andric 
2015ffd83dbSDimitry Andric     MatchInfo.CvtVal = Src0;
2025ffd83dbSDimitry Andric     MatchInfo.ShiftOffset = ShiftOffset;
2035ffd83dbSDimitry Andric     return ShiftOffset < 32 && ShiftOffset >= 8 && (ShiftOffset % 8) == 0;
2045ffd83dbSDimitry Andric   }
2055ffd83dbSDimitry Andric 
2065ffd83dbSDimitry Andric   // TODO: Simplify demanded bits.
2075ffd83dbSDimitry Andric   return false;
2085ffd83dbSDimitry Andric }
2095ffd83dbSDimitry Andric 
2105ffd83dbSDimitry Andric static void applyCvtF32UByteN(MachineInstr &MI,
2115ffd83dbSDimitry Andric                               const CvtF32UByteMatchInfo &MatchInfo) {
2125ffd83dbSDimitry Andric   MachineIRBuilder B(MI);
2135ffd83dbSDimitry Andric   unsigned NewOpc = AMDGPU::G_AMDGPU_CVT_F32_UBYTE0 + MatchInfo.ShiftOffset / 8;
2145ffd83dbSDimitry Andric 
2155ffd83dbSDimitry Andric   const LLT S32 = LLT::scalar(32);
2165ffd83dbSDimitry Andric   Register CvtSrc = MatchInfo.CvtVal;
2175ffd83dbSDimitry Andric   LLT SrcTy = B.getMRI()->getType(MatchInfo.CvtVal);
2185ffd83dbSDimitry Andric   if (SrcTy != S32) {
2195ffd83dbSDimitry Andric     assert(SrcTy.isScalar() && SrcTy.getSizeInBits() >= 8);
2205ffd83dbSDimitry Andric     CvtSrc = B.buildAnyExt(S32, CvtSrc).getReg(0);
2215ffd83dbSDimitry Andric   }
2225ffd83dbSDimitry Andric 
2235ffd83dbSDimitry Andric   assert(MI.getOpcode() != NewOpc);
2245ffd83dbSDimitry Andric   B.buildInstr(NewOpc, {MI.getOperand(0)}, {CvtSrc}, MI.getFlags());
2255ffd83dbSDimitry Andric   MI.eraseFromParent();
2265ffd83dbSDimitry Andric }
2275ffd83dbSDimitry Andric 
2285ffd83dbSDimitry Andric #define AMDGPUPOSTLEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_DEPS
2295ffd83dbSDimitry Andric #include "AMDGPUGenPostLegalizeGICombiner.inc"
2305ffd83dbSDimitry Andric #undef AMDGPUPOSTLEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_DEPS
2315ffd83dbSDimitry Andric 
2325ffd83dbSDimitry Andric namespace {
2335ffd83dbSDimitry Andric #define AMDGPUPOSTLEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_H
2345ffd83dbSDimitry Andric #include "AMDGPUGenPostLegalizeGICombiner.inc"
2355ffd83dbSDimitry Andric #undef AMDGPUPOSTLEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_H
2365ffd83dbSDimitry Andric 
2375ffd83dbSDimitry Andric class AMDGPUPostLegalizerCombinerInfo : public CombinerInfo {
2385ffd83dbSDimitry Andric   GISelKnownBits *KB;
2395ffd83dbSDimitry Andric   MachineDominatorTree *MDT;
2405ffd83dbSDimitry Andric 
2415ffd83dbSDimitry Andric public:
2425ffd83dbSDimitry Andric   AMDGPUGenPostLegalizerCombinerHelperRuleConfig GeneratedRuleCfg;
2435ffd83dbSDimitry Andric 
2445ffd83dbSDimitry Andric   AMDGPUPostLegalizerCombinerInfo(bool EnableOpt, bool OptSize, bool MinSize,
2455ffd83dbSDimitry Andric                                   const AMDGPULegalizerInfo *LI,
2465ffd83dbSDimitry Andric                                   GISelKnownBits *KB, MachineDominatorTree *MDT)
2475ffd83dbSDimitry Andric       : CombinerInfo(/*AllowIllegalOps*/ false, /*ShouldLegalizeIllegal*/ true,
2485ffd83dbSDimitry Andric                      /*LegalizerInfo*/ LI, EnableOpt, OptSize, MinSize),
2495ffd83dbSDimitry Andric         KB(KB), MDT(MDT) {
2505ffd83dbSDimitry Andric     if (!GeneratedRuleCfg.parseCommandLineOption())
2515ffd83dbSDimitry Andric       report_fatal_error("Invalid rule identifier");
2525ffd83dbSDimitry Andric   }
2535ffd83dbSDimitry Andric 
2545ffd83dbSDimitry Andric   bool combine(GISelChangeObserver &Observer, MachineInstr &MI,
2555ffd83dbSDimitry Andric                MachineIRBuilder &B) const override;
2565ffd83dbSDimitry Andric };
2575ffd83dbSDimitry Andric 
2585ffd83dbSDimitry Andric bool AMDGPUPostLegalizerCombinerInfo::combine(GISelChangeObserver &Observer,
2595ffd83dbSDimitry Andric                                               MachineInstr &MI,
2605ffd83dbSDimitry Andric                                               MachineIRBuilder &B) const {
2615ffd83dbSDimitry Andric   CombinerHelper Helper(Observer, B, KB, MDT);
2625ffd83dbSDimitry Andric   AMDGPUGenPostLegalizerCombinerHelper Generated(GeneratedRuleCfg);
2635ffd83dbSDimitry Andric 
2645ffd83dbSDimitry Andric   if (Generated.tryCombineAll(Observer, MI, B, Helper))
2655ffd83dbSDimitry Andric     return true;
2665ffd83dbSDimitry Andric 
2675ffd83dbSDimitry Andric   switch (MI.getOpcode()) {
2685ffd83dbSDimitry Andric   case TargetOpcode::G_SHL:
2695ffd83dbSDimitry Andric   case TargetOpcode::G_LSHR:
2705ffd83dbSDimitry Andric   case TargetOpcode::G_ASHR:
2715ffd83dbSDimitry Andric     // On some subtargets, 64-bit shift is a quarter rate instruction. In the
2725ffd83dbSDimitry Andric     // common case, splitting this into a move and a 32-bit shift is faster and
2735ffd83dbSDimitry Andric     // the same code size.
2745ffd83dbSDimitry Andric     return Helper.tryCombineShiftToUnmerge(MI, 32);
2755ffd83dbSDimitry Andric   }
2765ffd83dbSDimitry Andric 
2775ffd83dbSDimitry Andric   return false;
2785ffd83dbSDimitry Andric }
2795ffd83dbSDimitry Andric 
2805ffd83dbSDimitry Andric #define AMDGPUPOSTLEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_CPP
2815ffd83dbSDimitry Andric #include "AMDGPUGenPostLegalizeGICombiner.inc"
2825ffd83dbSDimitry Andric #undef AMDGPUPOSTLEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_CPP
2835ffd83dbSDimitry Andric 
2845ffd83dbSDimitry Andric // Pass boilerplate
2855ffd83dbSDimitry Andric // ================
2865ffd83dbSDimitry Andric 
2875ffd83dbSDimitry Andric class AMDGPUPostLegalizerCombiner : public MachineFunctionPass {
2885ffd83dbSDimitry Andric public:
2895ffd83dbSDimitry Andric   static char ID;
2905ffd83dbSDimitry Andric 
2915ffd83dbSDimitry Andric   AMDGPUPostLegalizerCombiner(bool IsOptNone = false);
2925ffd83dbSDimitry Andric 
2935ffd83dbSDimitry Andric   StringRef getPassName() const override {
2945ffd83dbSDimitry Andric     return "AMDGPUPostLegalizerCombiner";
2955ffd83dbSDimitry Andric   }
2965ffd83dbSDimitry Andric 
2975ffd83dbSDimitry Andric   bool runOnMachineFunction(MachineFunction &MF) override;
2985ffd83dbSDimitry Andric 
2995ffd83dbSDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override;
3005ffd83dbSDimitry Andric private:
3015ffd83dbSDimitry Andric   bool IsOptNone;
3025ffd83dbSDimitry Andric };
3035ffd83dbSDimitry Andric } // end anonymous namespace
3045ffd83dbSDimitry Andric 
3055ffd83dbSDimitry Andric void AMDGPUPostLegalizerCombiner::getAnalysisUsage(AnalysisUsage &AU) const {
3065ffd83dbSDimitry Andric   AU.addRequired<TargetPassConfig>();
3075ffd83dbSDimitry Andric   AU.setPreservesCFG();
3085ffd83dbSDimitry Andric   getSelectionDAGFallbackAnalysisUsage(AU);
3095ffd83dbSDimitry Andric   AU.addRequired<GISelKnownBitsAnalysis>();
3105ffd83dbSDimitry Andric   AU.addPreserved<GISelKnownBitsAnalysis>();
3115ffd83dbSDimitry Andric   if (!IsOptNone) {
3125ffd83dbSDimitry Andric     AU.addRequired<MachineDominatorTree>();
3135ffd83dbSDimitry Andric     AU.addPreserved<MachineDominatorTree>();
3145ffd83dbSDimitry Andric   }
3155ffd83dbSDimitry Andric   MachineFunctionPass::getAnalysisUsage(AU);
3165ffd83dbSDimitry Andric }
3175ffd83dbSDimitry Andric 
3185ffd83dbSDimitry Andric AMDGPUPostLegalizerCombiner::AMDGPUPostLegalizerCombiner(bool IsOptNone)
3195ffd83dbSDimitry Andric   : MachineFunctionPass(ID), IsOptNone(IsOptNone) {
3205ffd83dbSDimitry Andric   initializeAMDGPUPostLegalizerCombinerPass(*PassRegistry::getPassRegistry());
3215ffd83dbSDimitry Andric }
3225ffd83dbSDimitry Andric 
3235ffd83dbSDimitry Andric bool AMDGPUPostLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) {
3245ffd83dbSDimitry Andric   if (MF.getProperties().hasProperty(
3255ffd83dbSDimitry Andric           MachineFunctionProperties::Property::FailedISel))
3265ffd83dbSDimitry Andric     return false;
3275ffd83dbSDimitry Andric   auto *TPC = &getAnalysis<TargetPassConfig>();
3285ffd83dbSDimitry Andric   const Function &F = MF.getFunction();
3295ffd83dbSDimitry Andric   bool EnableOpt =
3305ffd83dbSDimitry Andric       MF.getTarget().getOptLevel() != CodeGenOpt::None && !skipFunction(F);
3315ffd83dbSDimitry Andric 
3325ffd83dbSDimitry Andric   const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
3335ffd83dbSDimitry Andric   const AMDGPULegalizerInfo *LI
3345ffd83dbSDimitry Andric     = static_cast<const AMDGPULegalizerInfo *>(ST.getLegalizerInfo());
3355ffd83dbSDimitry Andric 
3365ffd83dbSDimitry Andric   GISelKnownBits *KB = &getAnalysis<GISelKnownBitsAnalysis>().get(MF);
3375ffd83dbSDimitry Andric   MachineDominatorTree *MDT =
3385ffd83dbSDimitry Andric       IsOptNone ? nullptr : &getAnalysis<MachineDominatorTree>();
3395ffd83dbSDimitry Andric   AMDGPUPostLegalizerCombinerInfo PCInfo(EnableOpt, F.hasOptSize(),
3405ffd83dbSDimitry Andric                                          F.hasMinSize(), LI, KB, MDT);
3415ffd83dbSDimitry Andric   Combiner C(PCInfo, TPC);
3425ffd83dbSDimitry Andric   return C.combineMachineInstrs(MF, /*CSEInfo*/ nullptr);
3435ffd83dbSDimitry Andric }
3445ffd83dbSDimitry Andric 
3455ffd83dbSDimitry Andric char AMDGPUPostLegalizerCombiner::ID = 0;
3465ffd83dbSDimitry Andric INITIALIZE_PASS_BEGIN(AMDGPUPostLegalizerCombiner, DEBUG_TYPE,
3475ffd83dbSDimitry Andric                       "Combine AMDGPU machine instrs after legalization",
3485ffd83dbSDimitry Andric                       false, false)
3495ffd83dbSDimitry Andric INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
3505ffd83dbSDimitry Andric INITIALIZE_PASS_DEPENDENCY(GISelKnownBitsAnalysis)
3515ffd83dbSDimitry Andric INITIALIZE_PASS_END(AMDGPUPostLegalizerCombiner, DEBUG_TYPE,
3525ffd83dbSDimitry Andric                     "Combine AMDGPU machine instrs after legalization", false,
3535ffd83dbSDimitry Andric                     false)
3545ffd83dbSDimitry Andric 
3555ffd83dbSDimitry Andric namespace llvm {
3565ffd83dbSDimitry Andric FunctionPass *createAMDGPUPostLegalizeCombiner(bool IsOptNone) {
3575ffd83dbSDimitry Andric   return new AMDGPUPostLegalizerCombiner(IsOptNone);
3585ffd83dbSDimitry Andric }
3595ffd83dbSDimitry Andric } // end namespace llvm
360