@@ -372,6 +372,36 @@ inline bind_ty<LLT> m_Type(LLT &Ty) { return Ty; }
372
372
inline bind_ty<CmpInst::Predicate> m_Pred (CmpInst::Predicate &P) { return P; }
373
373
inline operand_type_match m_Pred () { return operand_type_match (); }
374
374
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
+
375
405
struct ImplicitDefMatch {
376
406
bool match (const MachineRegisterInfo &MRI, Register Reg) {
377
407
MachineInstr *TmpMI;
@@ -401,8 +431,13 @@ struct BinaryOp_match {
401
431
if (TmpMI->getOpcode () == Opcode && TmpMI->getNumOperands () == 3 ) {
402
432
return (L.match (MRI, TmpMI->getOperand (1 ).getReg ()) &&
403
433
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 ())));
406
441
}
407
442
}
408
443
return false ;
@@ -426,8 +461,13 @@ struct BinaryOpc_match {
426
461
TmpMI->getNumOperands () == 3 ) {
427
462
return (L.match (MRI, TmpMI->getOperand (1 ).getReg ()) &&
428
463
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 ())));
431
471
}
432
472
}
433
473
return false ;
@@ -674,6 +714,10 @@ struct CompareOp_match {
674
714
Register RHS = TmpMI->getOperand (3 ).getReg ();
675
715
if (L.match (MRI, LHS) && R.match (MRI, RHS))
676
716
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.
677
721
if (Commutable && L.match (MRI, RHS) && R.match (MRI, LHS) &&
678
722
P.match (MRI, CmpInst::getSwappedPredicate (TmpPred)))
679
723
return true ;
0 commit comments