|
17 | 17 | using namespace llvm; |
18 | 18 | using namespace MIPatternMatch; |
19 | 19 |
|
| 20 | +AMDGPUCombinerHelper::AMDGPUCombinerHelper( |
| 21 | + GISelChangeObserver &Observer, MachineIRBuilder &B, bool IsPreLegalize, |
| 22 | + GISelKnownBits *KB, MachineDominatorTree *MDT, const LegalizerInfo *LI, |
| 23 | + const GCNSubtarget &STI) |
| 24 | + : CombinerHelper(Observer, B, IsPreLegalize, KB, MDT, LI), STI(STI), |
| 25 | + TII(*STI.getInstrInfo()) {} |
| 26 | + |
20 | 27 | LLVM_READNONE |
21 | 28 | static bool fnegFoldsIntoMI(const MachineInstr &MI) { |
22 | 29 | switch (MI.getOpcode()) { |
@@ -445,3 +452,67 @@ void AMDGPUCombinerHelper::applyExpandPromotedF16FMed3(MachineInstr &MI, |
445 | 452 | Builder.buildFMinNumIEEE(MI.getOperand(0), B1, C1); |
446 | 453 | MI.eraseFromParent(); |
447 | 454 | } |
| 455 | + |
| 456 | +bool AMDGPUCombinerHelper::matchCombineFmulWithSelectToFldexp( |
| 457 | + MachineInstr &MI, MachineInstr &Sel, |
| 458 | + std::function<void(MachineIRBuilder &)> &MatchInfo) { |
| 459 | + assert(MI.getOpcode() == TargetOpcode::G_FMUL); |
| 460 | + assert(Sel.getOpcode() == TargetOpcode::G_SELECT); |
| 461 | + assert(MI.getOperand(2).getReg() == Sel.getOperand(0).getReg()); |
| 462 | + |
| 463 | + Register Dst = MI.getOperand(0).getReg(); |
| 464 | + LLT DestTy = MRI.getType(Dst); |
| 465 | + LLT ScalarDestTy = DestTy.getScalarType(); |
| 466 | + |
| 467 | + if ((ScalarDestTy != LLT::float64() && ScalarDestTy != LLT::float32() && |
| 468 | + ScalarDestTy != LLT::float16()) || |
| 469 | + !MRI.hasOneNonDBGUse(Sel.getOperand(0).getReg())) |
| 470 | + return false; |
| 471 | + |
| 472 | + Register SelectCondReg = Sel.getOperand(1).getReg(); |
| 473 | + MachineInstr *SelectTrue = MRI.getVRegDef(Sel.getOperand(2).getReg()); |
| 474 | + MachineInstr *SelectFalse = MRI.getVRegDef(Sel.getOperand(3).getReg()); |
| 475 | + |
| 476 | + const auto SelectTrueVal = |
| 477 | + isConstantOrConstantSplatVectorFP(*SelectTrue, MRI); |
| 478 | + if (!SelectTrueVal) |
| 479 | + return false; |
| 480 | + const auto SelectFalseVal = |
| 481 | + isConstantOrConstantSplatVectorFP(*SelectFalse, MRI); |
| 482 | + if (!SelectFalseVal) |
| 483 | + return false; |
| 484 | + |
| 485 | + if (SelectTrueVal->isNegative() != SelectFalseVal->isNegative()) |
| 486 | + return false; |
| 487 | + |
| 488 | + // For f32, only non-inline constants should be transformed. |
| 489 | + if (ScalarDestTy == LLT::float32() && TII.isInlineConstant(*SelectTrueVal) && |
| 490 | + TII.isInlineConstant(*SelectFalseVal)) |
| 491 | + return false; |
| 492 | + |
| 493 | + int SelectTrueLog2Val = SelectTrueVal->getExactLog2Abs(); |
| 494 | + if (SelectTrueLog2Val == INT_MIN) |
| 495 | + return false; |
| 496 | + int SelectFalseLog2Val = SelectFalseVal->getExactLog2Abs(); |
| 497 | + if (SelectFalseLog2Val == INT_MIN) |
| 498 | + return false; |
| 499 | + |
| 500 | + MatchInfo = [=, &MI](MachineIRBuilder &Builder) { |
| 501 | + LLT IntDestTy = DestTy.changeElementType(LLT::scalar(32)); |
| 502 | + auto NewSel = Builder.buildSelect( |
| 503 | + IntDestTy, SelectCondReg, |
| 504 | + Builder.buildConstant(IntDestTy, SelectTrueLog2Val), |
| 505 | + Builder.buildConstant(IntDestTy, SelectFalseLog2Val)); |
| 506 | + |
| 507 | + Register XReg = MI.getOperand(1).getReg(); |
| 508 | + if (SelectTrueVal->isNegative()) { |
| 509 | + auto NegX = |
| 510 | + Builder.buildFNeg(DestTy, XReg, MRI.getVRegDef(XReg)->getFlags()); |
| 511 | + Builder.buildFLdexp(Dst, NegX, NewSel, MI.getFlags()); |
| 512 | + } else { |
| 513 | + Builder.buildFLdexp(Dst, XReg, NewSel, MI.getFlags()); |
| 514 | + } |
| 515 | + }; |
| 516 | + |
| 517 | + return true; |
| 518 | +} |
0 commit comments