1 //=== lib/CodeGen/GlobalISel/AMDGPURegBankCombiner.cpp ---------------===// 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 // This pass does combining of machine instructions at the generic MI level, 10 // after register banks are known. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "AMDGPU.h" 15 #include "AMDGPULegalizerInfo.h" 16 #include "AMDGPURegisterBankInfo.h" 17 #include "GCNSubtarget.h" 18 #include "MCTargetDesc/AMDGPUMCTargetDesc.h" 19 #include "SIMachineFunctionInfo.h" 20 #include "llvm/CodeGen/GlobalISel/Combiner.h" 21 #include "llvm/CodeGen/GlobalISel/CombinerHelper.h" 22 #include "llvm/CodeGen/GlobalISel/CombinerInfo.h" 23 #include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h" 24 #include "llvm/CodeGen/GlobalISel/GISelKnownBits.h" 25 #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h" 26 #include "llvm/CodeGen/MachineDominators.h" 27 #include "llvm/CodeGen/TargetPassConfig.h" 28 #include "llvm/Target/TargetMachine.h" 29 30 #define GET_GICOMBINER_DEPS 31 #include "AMDGPUGenPreLegalizeGICombiner.inc" 32 #undef GET_GICOMBINER_DEPS 33 34 #define DEBUG_TYPE "amdgpu-regbank-combiner" 35 36 using namespace llvm; 37 using namespace MIPatternMatch; 38 39 namespace { 40 #define GET_GICOMBINER_TYPES 41 #include "AMDGPUGenRegBankGICombiner.inc" 42 #undef GET_GICOMBINER_TYPES 43 44 class AMDGPURegBankCombinerImpl : public Combiner { 45 protected: 46 const AMDGPURegBankCombinerImplRuleConfig &RuleConfig; 47 const GCNSubtarget &STI; 48 const RegisterBankInfo &RBI; 49 const TargetRegisterInfo &TRI; 50 const SIInstrInfo &TII; 51 const CombinerHelper Helper; 52 53 public: 54 AMDGPURegBankCombinerImpl( 55 MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC, 56 GISelKnownBits &KB, GISelCSEInfo *CSEInfo, 57 const AMDGPURegBankCombinerImplRuleConfig &RuleConfig, 58 const GCNSubtarget &STI, MachineDominatorTree *MDT, 59 const LegalizerInfo *LI); 60 61 static const char *getName() { return "AMDGPURegBankCombinerImpl"; } 62 63 bool tryCombineAll(MachineInstr &I) const override; 64 65 bool isVgprRegBank(Register Reg) const; 66 Register getAsVgpr(Register Reg) const; 67 68 struct MinMaxMedOpc { 69 unsigned Min, Max, Med; 70 }; 71 72 struct Med3MatchInfo { 73 unsigned Opc; 74 Register Val0, Val1, Val2; 75 }; 76 77 MinMaxMedOpc getMinMaxPair(unsigned Opc) const; 78 79 template <class m_Cst, typename CstTy> 80 bool matchMed(MachineInstr &MI, MachineRegisterInfo &MRI, MinMaxMedOpc MMMOpc, 81 Register &Val, CstTy &K0, CstTy &K1) const; 82 83 bool matchIntMinMaxToMed3(MachineInstr &MI, Med3MatchInfo &MatchInfo) const; 84 bool matchFPMinMaxToMed3(MachineInstr &MI, Med3MatchInfo &MatchInfo) const; 85 bool matchFPMinMaxToClamp(MachineInstr &MI, Register &Reg) const; 86 bool matchFPMed3ToClamp(MachineInstr &MI, Register &Reg) const; 87 void applyMed3(MachineInstr &MI, Med3MatchInfo &MatchInfo) const; 88 void applyClamp(MachineInstr &MI, Register &Reg) const; 89 90 private: 91 SIModeRegisterDefaults getMode() const; 92 bool getIEEE() const; 93 bool getDX10Clamp() const; 94 bool isFminnumIeee(const MachineInstr &MI) const; 95 bool isFCst(MachineInstr *MI) const; 96 bool isClampZeroToOne(MachineInstr *K0, MachineInstr *K1) const; 97 98 #define GET_GICOMBINER_CLASS_MEMBERS 99 #define AMDGPUSubtarget GCNSubtarget 100 #include "AMDGPUGenRegBankGICombiner.inc" 101 #undef GET_GICOMBINER_CLASS_MEMBERS 102 #undef AMDGPUSubtarget 103 }; 104 105 #define GET_GICOMBINER_IMPL 106 #define AMDGPUSubtarget GCNSubtarget 107 #include "AMDGPUGenRegBankGICombiner.inc" 108 #undef AMDGPUSubtarget 109 #undef GET_GICOMBINER_IMPL 110 111 AMDGPURegBankCombinerImpl::AMDGPURegBankCombinerImpl( 112 MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC, 113 GISelKnownBits &KB, GISelCSEInfo *CSEInfo, 114 const AMDGPURegBankCombinerImplRuleConfig &RuleConfig, 115 const GCNSubtarget &STI, MachineDominatorTree *MDT, const LegalizerInfo *LI) 116 : Combiner(MF, CInfo, TPC, &KB, CSEInfo), RuleConfig(RuleConfig), STI(STI), 117 RBI(*STI.getRegBankInfo()), TRI(*STI.getRegisterInfo()), 118 TII(*STI.getInstrInfo()), 119 Helper(Observer, B, /*IsPreLegalize*/ false, &KB, MDT, LI), 120 #define GET_GICOMBINER_CONSTRUCTOR_INITS 121 #include "AMDGPUGenRegBankGICombiner.inc" 122 #undef GET_GICOMBINER_CONSTRUCTOR_INITS 123 { 124 } 125 126 bool AMDGPURegBankCombinerImpl::isVgprRegBank(Register Reg) const { 127 return RBI.getRegBank(Reg, MRI, TRI)->getID() == AMDGPU::VGPRRegBankID; 128 } 129 130 Register AMDGPURegBankCombinerImpl::getAsVgpr(Register Reg) const { 131 if (isVgprRegBank(Reg)) 132 return Reg; 133 134 // Search for existing copy of Reg to vgpr. 135 for (MachineInstr &Use : MRI.use_instructions(Reg)) { 136 Register Def = Use.getOperand(0).getReg(); 137 if (Use.getOpcode() == AMDGPU::COPY && isVgprRegBank(Def)) 138 return Def; 139 } 140 141 // Copy Reg to vgpr. 142 Register VgprReg = B.buildCopy(MRI.getType(Reg), Reg).getReg(0); 143 MRI.setRegBank(VgprReg, RBI.getRegBank(AMDGPU::VGPRRegBankID)); 144 return VgprReg; 145 } 146 147 AMDGPURegBankCombinerImpl::MinMaxMedOpc 148 AMDGPURegBankCombinerImpl::getMinMaxPair(unsigned Opc) const { 149 switch (Opc) { 150 default: 151 llvm_unreachable("Unsupported opcode"); 152 case AMDGPU::G_SMAX: 153 case AMDGPU::G_SMIN: 154 return {AMDGPU::G_SMIN, AMDGPU::G_SMAX, AMDGPU::G_AMDGPU_SMED3}; 155 case AMDGPU::G_UMAX: 156 case AMDGPU::G_UMIN: 157 return {AMDGPU::G_UMIN, AMDGPU::G_UMAX, AMDGPU::G_AMDGPU_UMED3}; 158 case AMDGPU::G_FMAXNUM: 159 case AMDGPU::G_FMINNUM: 160 return {AMDGPU::G_FMINNUM, AMDGPU::G_FMAXNUM, AMDGPU::G_AMDGPU_FMED3}; 161 case AMDGPU::G_FMAXNUM_IEEE: 162 case AMDGPU::G_FMINNUM_IEEE: 163 return {AMDGPU::G_FMINNUM_IEEE, AMDGPU::G_FMAXNUM_IEEE, 164 AMDGPU::G_AMDGPU_FMED3}; 165 } 166 } 167 168 template <class m_Cst, typename CstTy> 169 bool AMDGPURegBankCombinerImpl::matchMed(MachineInstr &MI, 170 MachineRegisterInfo &MRI, 171 MinMaxMedOpc MMMOpc, Register &Val, 172 CstTy &K0, CstTy &K1) const { 173 // 4 operand commutes of: min(max(Val, K0), K1). 174 // Find K1 from outer instr: min(max(...), K1) or min(K1, max(...)). 175 // Find K0 and Val from inner instr: max(K0, Val) or max(Val, K0). 176 // 4 operand commutes of: max(min(Val, K1), K0). 177 // Find K0 from outer instr: max(min(...), K0) or max(K0, min(...)). 178 // Find K1 and Val from inner instr: min(K1, Val) or min(Val, K1). 179 return mi_match( 180 MI, MRI, 181 m_any_of( 182 m_CommutativeBinOp( 183 MMMOpc.Min, m_CommutativeBinOp(MMMOpc.Max, m_Reg(Val), m_Cst(K0)), 184 m_Cst(K1)), 185 m_CommutativeBinOp( 186 MMMOpc.Max, m_CommutativeBinOp(MMMOpc.Min, m_Reg(Val), m_Cst(K1)), 187 m_Cst(K0)))); 188 } 189 190 bool AMDGPURegBankCombinerImpl::matchIntMinMaxToMed3( 191 MachineInstr &MI, Med3MatchInfo &MatchInfo) const { 192 Register Dst = MI.getOperand(0).getReg(); 193 if (!isVgprRegBank(Dst)) 194 return false; 195 196 // med3 for i16 is only available on gfx9+, and not available for v2i16. 197 LLT Ty = MRI.getType(Dst); 198 if ((Ty != LLT::scalar(16) || !STI.hasMed3_16()) && Ty != LLT::scalar(32)) 199 return false; 200 201 MinMaxMedOpc OpcodeTriple = getMinMaxPair(MI.getOpcode()); 202 Register Val; 203 std::optional<ValueAndVReg> K0, K1; 204 // Match min(max(Val, K0), K1) or max(min(Val, K1), K0). Then see if K0 <= K1. 205 if (!matchMed<GCstAndRegMatch>(MI, MRI, OpcodeTriple, Val, K0, K1)) 206 return false; 207 208 if (OpcodeTriple.Med == AMDGPU::G_AMDGPU_SMED3 && K0->Value.sgt(K1->Value)) 209 return false; 210 if (OpcodeTriple.Med == AMDGPU::G_AMDGPU_UMED3 && K0->Value.ugt(K1->Value)) 211 return false; 212 213 MatchInfo = {OpcodeTriple.Med, Val, K0->VReg, K1->VReg}; 214 return true; 215 } 216 217 // fmed3(NaN, K0, K1) = min(min(NaN, K0), K1) 218 // ieee = true : min/max(SNaN, K) = QNaN, min/max(QNaN, K) = K 219 // ieee = false : min/max(NaN, K) = K 220 // clamp(NaN) = dx10_clamp ? 0.0 : NaN 221 // Consider values of min(max(Val, K0), K1) and max(min(Val, K1), K0) as input. 222 // Other operand commutes (see matchMed) give same result since min and max are 223 // commutative. 224 225 // Try to replace fp min(max(Val, K0), K1) or max(min(Val, K1), K0), KO<=K1 226 // with fmed3(Val, K0, K1) or clamp(Val). Clamp requires K0 = 0.0 and K1 = 1.0. 227 // Val = SNaN only for ieee = true 228 // fmed3(SNaN, K0, K1) = min(min(SNaN, K0), K1) = min(QNaN, K1) = K1 229 // min(max(SNaN, K0), K1) = min(QNaN, K1) = K1 230 // max(min(SNaN, K1), K0) = max(K1, K0) = K1 231 // Val = NaN,ieee = false or Val = QNaN,ieee = true 232 // fmed3(NaN, K0, K1) = min(min(NaN, K0), K1) = min(K0, K1) = K0 233 // min(max(NaN, K0), K1) = min(K0, K1) = K0 (can clamp when dx10_clamp = true) 234 // max(min(NaN, K1), K0) = max(K1, K0) = K1 != K0 235 bool AMDGPURegBankCombinerImpl::matchFPMinMaxToMed3( 236 MachineInstr &MI, Med3MatchInfo &MatchInfo) const { 237 Register Dst = MI.getOperand(0).getReg(); 238 LLT Ty = MRI.getType(Dst); 239 240 // med3 for f16 is only available on gfx9+, and not available for v2f16. 241 if ((Ty != LLT::scalar(16) || !STI.hasMed3_16()) && Ty != LLT::scalar(32)) 242 return false; 243 244 auto OpcodeTriple = getMinMaxPair(MI.getOpcode()); 245 246 Register Val; 247 std::optional<FPValueAndVReg> K0, K1; 248 // Match min(max(Val, K0), K1) or max(min(Val, K1), K0). Then see if K0 <= K1. 249 if (!matchMed<GFCstAndRegMatch>(MI, MRI, OpcodeTriple, Val, K0, K1)) 250 return false; 251 252 if (K0->Value > K1->Value) 253 return false; 254 255 // For IEEE=false perform combine only when it's safe to assume that there are 256 // no NaN inputs. Most often MI is marked with nnan fast math flag. 257 // For IEEE=true consider NaN inputs. fmed3(NaN, K0, K1) is equivalent to 258 // min(min(NaN, K0), K1). Safe to fold for min(max(Val, K0), K1) since inner 259 // nodes(max/min) have same behavior when one input is NaN and other isn't. 260 // Don't consider max(min(SNaN, K1), K0) since there is no isKnownNeverQNaN, 261 // also post-legalizer inputs to min/max are fcanonicalized (never SNaN). 262 if ((getIEEE() && isFminnumIeee(MI)) || isKnownNeverNaN(Dst, MRI)) { 263 // Don't fold single use constant that can't be inlined. 264 if ((!MRI.hasOneNonDBGUse(K0->VReg) || TII.isInlineConstant(K0->Value)) && 265 (!MRI.hasOneNonDBGUse(K1->VReg) || TII.isInlineConstant(K1->Value))) { 266 MatchInfo = {OpcodeTriple.Med, Val, K0->VReg, K1->VReg}; 267 return true; 268 } 269 } 270 271 return false; 272 } 273 274 bool AMDGPURegBankCombinerImpl::matchFPMinMaxToClamp(MachineInstr &MI, 275 Register &Reg) const { 276 // Clamp is available on all types after regbankselect (f16, f32, f64, v2f16). 277 auto OpcodeTriple = getMinMaxPair(MI.getOpcode()); 278 Register Val; 279 std::optional<FPValueAndVReg> K0, K1; 280 // Match min(max(Val, K0), K1) or max(min(Val, K1), K0). 281 if (!matchMed<GFCstOrSplatGFCstMatch>(MI, MRI, OpcodeTriple, Val, K0, K1)) 282 return false; 283 284 if (!K0->Value.isExactlyValue(0.0) || !K1->Value.isExactlyValue(1.0)) 285 return false; 286 287 // For IEEE=false perform combine only when it's safe to assume that there are 288 // no NaN inputs. Most often MI is marked with nnan fast math flag. 289 // For IEEE=true consider NaN inputs. Only min(max(QNaN, 0.0), 1.0) evaluates 290 // to 0.0 requires dx10_clamp = true. 291 if ((getIEEE() && getDX10Clamp() && isFminnumIeee(MI) && 292 isKnownNeverSNaN(Val, MRI)) || 293 isKnownNeverNaN(MI.getOperand(0).getReg(), MRI)) { 294 Reg = Val; 295 return true; 296 } 297 298 return false; 299 } 300 301 // Replacing fmed3(NaN, 0.0, 1.0) with clamp. Requires dx10_clamp = true. 302 // Val = SNaN only for ieee = true. It is important which operand is NaN. 303 // min(min(SNaN, 0.0), 1.0) = min(QNaN, 1.0) = 1.0 304 // min(min(SNaN, 1.0), 0.0) = min(QNaN, 0.0) = 0.0 305 // min(min(0.0, 1.0), SNaN) = min(0.0, SNaN) = QNaN 306 // Val = NaN,ieee = false or Val = QNaN,ieee = true 307 // min(min(NaN, 0.0), 1.0) = min(0.0, 1.0) = 0.0 308 // min(min(NaN, 1.0), 0.0) = min(1.0, 0.0) = 0.0 309 // min(min(0.0, 1.0), NaN) = min(0.0, NaN) = 0.0 310 bool AMDGPURegBankCombinerImpl::matchFPMed3ToClamp(MachineInstr &MI, 311 Register &Reg) const { 312 // In llvm-ir, clamp is often represented as an intrinsic call to 313 // @llvm.amdgcn.fmed3.f32(%Val, 0.0, 1.0). Check for other operand orders. 314 MachineInstr *Src0 = getDefIgnoringCopies(MI.getOperand(1).getReg(), MRI); 315 MachineInstr *Src1 = getDefIgnoringCopies(MI.getOperand(2).getReg(), MRI); 316 MachineInstr *Src2 = getDefIgnoringCopies(MI.getOperand(3).getReg(), MRI); 317 318 if (isFCst(Src0) && !isFCst(Src1)) 319 std::swap(Src0, Src1); 320 if (isFCst(Src1) && !isFCst(Src2)) 321 std::swap(Src1, Src2); 322 if (isFCst(Src0) && !isFCst(Src1)) 323 std::swap(Src0, Src1); 324 if (!isClampZeroToOne(Src1, Src2)) 325 return false; 326 327 Register Val = Src0->getOperand(0).getReg(); 328 329 auto isOp3Zero = [&]() { 330 MachineInstr *Op3 = getDefIgnoringCopies(MI.getOperand(4).getReg(), MRI); 331 if (Op3->getOpcode() == TargetOpcode::G_FCONSTANT) 332 return Op3->getOperand(1).getFPImm()->isExactlyValue(0.0); 333 return false; 334 }; 335 // For IEEE=false perform combine only when it's safe to assume that there are 336 // no NaN inputs. Most often MI is marked with nnan fast math flag. 337 // For IEEE=true consider NaN inputs. Requires dx10_clamp = true. Safe to fold 338 // when Val could be QNaN. If Val can also be SNaN third input should be 0.0. 339 if (isKnownNeverNaN(MI.getOperand(0).getReg(), MRI) || 340 (getIEEE() && getDX10Clamp() && 341 (isKnownNeverSNaN(Val, MRI) || isOp3Zero()))) { 342 Reg = Val; 343 return true; 344 } 345 346 return false; 347 } 348 349 void AMDGPURegBankCombinerImpl::applyClamp(MachineInstr &MI, 350 Register &Reg) const { 351 B.buildInstr(AMDGPU::G_AMDGPU_CLAMP, {MI.getOperand(0)}, {Reg}, 352 MI.getFlags()); 353 MI.eraseFromParent(); 354 } 355 356 void AMDGPURegBankCombinerImpl::applyMed3(MachineInstr &MI, 357 Med3MatchInfo &MatchInfo) const { 358 B.buildInstr(MatchInfo.Opc, {MI.getOperand(0)}, 359 {getAsVgpr(MatchInfo.Val0), getAsVgpr(MatchInfo.Val1), 360 getAsVgpr(MatchInfo.Val2)}, 361 MI.getFlags()); 362 MI.eraseFromParent(); 363 } 364 365 SIModeRegisterDefaults AMDGPURegBankCombinerImpl::getMode() const { 366 return MF.getInfo<SIMachineFunctionInfo>()->getMode(); 367 } 368 369 bool AMDGPURegBankCombinerImpl::getIEEE() const { return getMode().IEEE; } 370 371 bool AMDGPURegBankCombinerImpl::getDX10Clamp() const { 372 return getMode().DX10Clamp; 373 } 374 375 bool AMDGPURegBankCombinerImpl::isFminnumIeee(const MachineInstr &MI) const { 376 return MI.getOpcode() == AMDGPU::G_FMINNUM_IEEE; 377 } 378 379 bool AMDGPURegBankCombinerImpl::isFCst(MachineInstr *MI) const { 380 return MI->getOpcode() == AMDGPU::G_FCONSTANT; 381 } 382 383 bool AMDGPURegBankCombinerImpl::isClampZeroToOne(MachineInstr *K0, 384 MachineInstr *K1) const { 385 if (isFCst(K0) && isFCst(K1)) { 386 const ConstantFP *KO_FPImm = K0->getOperand(1).getFPImm(); 387 const ConstantFP *K1_FPImm = K1->getOperand(1).getFPImm(); 388 return (KO_FPImm->isExactlyValue(0.0) && K1_FPImm->isExactlyValue(1.0)) || 389 (KO_FPImm->isExactlyValue(1.0) && K1_FPImm->isExactlyValue(0.0)); 390 } 391 return false; 392 } 393 394 // Pass boilerplate 395 // ================ 396 397 class AMDGPURegBankCombiner : public MachineFunctionPass { 398 public: 399 static char ID; 400 401 AMDGPURegBankCombiner(bool IsOptNone = false); 402 403 StringRef getPassName() const override { return "AMDGPURegBankCombiner"; } 404 405 bool runOnMachineFunction(MachineFunction &MF) override; 406 407 void getAnalysisUsage(AnalysisUsage &AU) const override; 408 409 private: 410 bool IsOptNone; 411 AMDGPURegBankCombinerImplRuleConfig RuleConfig; 412 }; 413 } // end anonymous namespace 414 415 void AMDGPURegBankCombiner::getAnalysisUsage(AnalysisUsage &AU) const { 416 AU.addRequired<TargetPassConfig>(); 417 AU.setPreservesCFG(); 418 getSelectionDAGFallbackAnalysisUsage(AU); 419 AU.addRequired<GISelKnownBitsAnalysis>(); 420 AU.addPreserved<GISelKnownBitsAnalysis>(); 421 if (!IsOptNone) { 422 AU.addRequired<MachineDominatorTreeWrapperPass>(); 423 AU.addPreserved<MachineDominatorTreeWrapperPass>(); 424 } 425 MachineFunctionPass::getAnalysisUsage(AU); 426 } 427 428 AMDGPURegBankCombiner::AMDGPURegBankCombiner(bool IsOptNone) 429 : MachineFunctionPass(ID), IsOptNone(IsOptNone) { 430 initializeAMDGPURegBankCombinerPass(*PassRegistry::getPassRegistry()); 431 432 if (!RuleConfig.parseCommandLineOption()) 433 report_fatal_error("Invalid rule identifier"); 434 } 435 436 bool AMDGPURegBankCombiner::runOnMachineFunction(MachineFunction &MF) { 437 if (MF.getProperties().hasProperty( 438 MachineFunctionProperties::Property::FailedISel)) 439 return false; 440 auto *TPC = &getAnalysis<TargetPassConfig>(); 441 const Function &F = MF.getFunction(); 442 bool EnableOpt = 443 MF.getTarget().getOptLevel() != CodeGenOptLevel::None && !skipFunction(F); 444 445 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>(); 446 GISelKnownBits *KB = &getAnalysis<GISelKnownBitsAnalysis>().get(MF); 447 448 const auto *LI = ST.getLegalizerInfo(); 449 MachineDominatorTree *MDT = 450 IsOptNone ? nullptr 451 : &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree(); 452 453 CombinerInfo CInfo(/*AllowIllegalOps*/ false, /*ShouldLegalizeIllegal*/ true, 454 LI, EnableOpt, F.hasOptSize(), F.hasMinSize()); 455 // Disable fixed-point iteration to reduce compile-time 456 CInfo.MaxIterations = 1; 457 CInfo.ObserverLvl = CombinerInfo::ObserverLevel::SinglePass; 458 // RegBankSelect seems not to leave dead instructions, so a full DCE pass is 459 // unnecessary. 460 CInfo.EnableFullDCE = false; 461 AMDGPURegBankCombinerImpl Impl(MF, CInfo, TPC, *KB, /*CSEInfo*/ nullptr, 462 RuleConfig, ST, MDT, LI); 463 return Impl.combineMachineInstrs(); 464 } 465 466 char AMDGPURegBankCombiner::ID = 0; 467 INITIALIZE_PASS_BEGIN(AMDGPURegBankCombiner, DEBUG_TYPE, 468 "Combine AMDGPU machine instrs after regbankselect", 469 false, false) 470 INITIALIZE_PASS_DEPENDENCY(TargetPassConfig) 471 INITIALIZE_PASS_DEPENDENCY(GISelKnownBitsAnalysis) 472 INITIALIZE_PASS_END(AMDGPURegBankCombiner, DEBUG_TYPE, 473 "Combine AMDGPU machine instrs after regbankselect", false, 474 false) 475 476 namespace llvm { 477 FunctionPass *createAMDGPURegBankCombiner(bool IsOptNone) { 478 return new AMDGPURegBankCombiner(IsOptNone); 479 } 480 } // end namespace llvm 481