@@ -372,6 +372,36 @@ inline bind_ty<LLT> m_Type(LLT &Ty) { return Ty; }
372372inline bind_ty<CmpInst::Predicate> m_Pred (CmpInst::Predicate &P) { return P; }
373373inline operand_type_match m_Pred () { return operand_type_match (); }
374374
375+ template <typename BindTy> struct deferred_helper {
376+ static bool match (const MachineRegisterInfo &MRI, BindTy &VR, BindTy &V) {
377+ return VR == V;
378+ }
379+ };
380+
381+ template <> struct deferred_helper <LLT> {
382+ static bool match (const MachineRegisterInfo &MRI, LLT VT, Register R) {
383+ return VT == MRI.getType (R);
384+ }
385+ };
386+
387+ template <typename Class> struct deferred_ty {
388+ Class &VR;
389+
390+ deferred_ty (Class &V) : VR(V) {}
391+
392+ template <typename ITy> bool match (const MachineRegisterInfo &MRI, ITy &&V) {
393+ return deferred_helper<Class>::match (MRI, VR, V);
394+ }
395+ };
396+
397+ // / Similar to m_SpecificReg/Type, but the specific value to match originated
398+ // / from an earlier sub-pattern in the same mi_match expression. For example,
399+ // / we cannot match `(add X, X)` with `m_GAdd(m_Reg(X), m_SpecificReg(X))`
400+ // / because `X` is not initialized at the time it's passed to `m_SpecificReg`.
401+ // / Instead, we can use `m_GAdd(m_Reg(x), m_DeferredReg(X))`.
402+ inline deferred_ty<Register> m_DeferredReg (Register &R) { return R; }
403+ inline deferred_ty<LLT> m_DeferredType (LLT &Ty) { return Ty; }
404+
375405struct ImplicitDefMatch {
376406 bool match (const MachineRegisterInfo &MRI, Register Reg) {
377407 MachineInstr *TmpMI;
@@ -401,8 +431,13 @@ struct BinaryOp_match {
401431 if (TmpMI->getOpcode () == Opcode && TmpMI->getNumOperands () == 3 ) {
402432 return (L.match (MRI, TmpMI->getOperand (1 ).getReg ()) &&
403433 R.match (MRI, TmpMI->getOperand (2 ).getReg ())) ||
404- (Commutable && (R.match (MRI, TmpMI->getOperand (1 ).getReg ()) &&
405- L.match (MRI, TmpMI->getOperand (2 ).getReg ())));
434+ // NOTE: When trying the alternative operand ordering
435+ // with a commutative operation, it is imperative to always run
436+ // the LHS sub-pattern (i.e. `L`) before the RHS sub-pattern
437+ // (i.e. `R`). Otherwsie, m_DeferredReg/Type will not work as
438+ // expected.
439+ (Commutable && (L.match (MRI, TmpMI->getOperand (2 ).getReg ()) &&
440+ R.match (MRI, TmpMI->getOperand (1 ).getReg ())));
406441 }
407442 }
408443 return false ;
@@ -426,8 +461,13 @@ struct BinaryOpc_match {
426461 TmpMI->getNumOperands () == 3 ) {
427462 return (L.match (MRI, TmpMI->getOperand (1 ).getReg ()) &&
428463 R.match (MRI, TmpMI->getOperand (2 ).getReg ())) ||
429- (Commutable && (R.match (MRI, TmpMI->getOperand (1 ).getReg ()) &&
430- L.match (MRI, TmpMI->getOperand (2 ).getReg ())));
464+ // NOTE: When trying the alternative operand ordering
465+ // with a commutative operation, it is imperative to always run
466+ // the LHS sub-pattern (i.e. `L`) before the RHS sub-pattern
467+ // (i.e. `R`). Otherwsie, m_DeferredReg/Type will not work as
468+ // expected.
469+ (Commutable && (L.match (MRI, TmpMI->getOperand (2 ).getReg ()) &&
470+ R.match (MRI, TmpMI->getOperand (1 ).getReg ())));
431471 }
432472 }
433473 return false ;
@@ -674,6 +714,10 @@ struct CompareOp_match {
674714 Register RHS = TmpMI->getOperand (3 ).getReg ();
675715 if (L.match (MRI, LHS) && R.match (MRI, RHS))
676716 return true ;
717+ // NOTE: When trying the alternative operand ordering
718+ // with a commutative operation, it is imperative to always run
719+ // the LHS sub-pattern (i.e. `L`) before the RHS sub-pattern
720+ // (i.e. `R`). Otherwsie, m_DeferredReg/Type will not work as expected.
677721 if (Commutable && L.match (MRI, RHS) && R.match (MRI, LHS) &&
678722 P.match (MRI, CmpInst::getSwappedPredicate (TmpPred)))
679723 return true ;
0 commit comments