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