@@ -2505,18 +2505,8 @@ bool RISCVDAGToDAGISel::doPeepholeSExtW(SDNode *N) {
2505
2505
return false ;
2506
2506
}
2507
2507
2508
- // Optimize masked RVV pseudo instructions with a known all-ones mask to their
2509
- // corresponding "unmasked" pseudo versions. The mask we're interested in will
2510
- // take the form of a V0 physical register operand, with a glued
2511
- // register-setting instruction.
2512
- bool RISCVDAGToDAGISel::doPeepholeMaskedRVV (SDNode *N) {
2513
- const RISCV::RISCVMaskedPseudoInfo *I =
2514
- RISCV::getMaskedPseudoInfo (N->getMachineOpcode ());
2515
- if (!I)
2516
- return false ;
2517
-
2518
- unsigned MaskOpIdx = I->MaskOpIdx ;
2519
-
2508
+ // Return true if we can make sure mask of N is all-ones mask.
2509
+ static bool usesAllOnesMask (SDNode *N, unsigned MaskOpIdx) {
2520
2510
// Check that we're using V0 as a mask register.
2521
2511
if (!isa<RegisterSDNode>(N->getOperand (MaskOpIdx)) ||
2522
2512
cast<RegisterSDNode>(N->getOperand (MaskOpIdx))->getReg () != RISCV::V0)
@@ -2546,7 +2536,23 @@ bool RISCVDAGToDAGISel::doPeepholeMaskedRVV(SDNode *N) {
2546
2536
// TODO: Check that the VMSET is the expected bitwidth? The pseudo has
2547
2537
// undefined behaviour if it's the wrong bitwidth, so we could choose to
2548
2538
// assume that it's all-ones? Same applies to its VL.
2549
- if (!MaskSetter->isMachineOpcode () || !IsVMSet (MaskSetter.getMachineOpcode ()))
2539
+ return MaskSetter->isMachineOpcode () &&
2540
+ IsVMSet (MaskSetter.getMachineOpcode ());
2541
+ }
2542
+
2543
+ // Optimize masked RVV pseudo instructions with a known all-ones mask to their
2544
+ // corresponding "unmasked" pseudo versions. The mask we're interested in will
2545
+ // take the form of a V0 physical register operand, with a glued
2546
+ // register-setting instruction.
2547
+ bool RISCVDAGToDAGISel::doPeepholeMaskedRVV (SDNode *N) {
2548
+ const RISCV::RISCVMaskedPseudoInfo *I =
2549
+ RISCV::getMaskedPseudoInfo (N->getMachineOpcode ());
2550
+ if (!I)
2551
+ return false ;
2552
+
2553
+ unsigned MaskOpIdx = I->MaskOpIdx ;
2554
+
2555
+ if (!usesAllOnesMask (N, MaskOpIdx))
2550
2556
return false ;
2551
2557
2552
2558
// Retrieve the tail policy operand index, if any.
@@ -2600,6 +2606,7 @@ bool RISCVDAGToDAGISel::doPeepholeMaskedRVV(SDNode *N) {
2600
2606
}
2601
2607
2602
2608
// Transitively apply any node glued to our new node.
2609
+ const auto *Glued = N->getGluedNode ();
2603
2610
if (auto *TGlued = Glued->getGluedNode ())
2604
2611
Ops.push_back (SDValue (TGlued, TGlued->getNumValues () - 1 ));
2605
2612
@@ -2614,121 +2621,167 @@ bool RISCVDAGToDAGISel::doPeepholeMaskedRVV(SDNode *N) {
2614
2621
// peephole only deals with VMERGE_VVM which is TU and has false operand same as
2615
2622
// its true operand now. E.g. (VMERGE_VVM_M1_TU False, False, (VADD_M1 ...),
2616
2623
// ...) -> (VADD_VV_M1_MASK)
2617
- bool RISCVDAGToDAGISel::doPeepholeMergeVVMFold () {
2618
- bool MadeChange = false ;
2619
- SelectionDAG::allnodes_iterator Position = CurDAG->allnodes_end ();
2624
+ bool RISCVDAGToDAGISel::performCombineVMergeAndVOps (SDNode *N) {
2625
+ SDValue Merge = N->getOperand (0 );
2626
+ SDValue True = N->getOperand (2 );
2627
+ SDValue Mask = N->getOperand (3 );
2628
+ SDValue VL = N->getOperand (4 );
2620
2629
2621
- while (Position != CurDAG->allnodes_begin ()) {
2622
- SDNode *N = &*--Position;
2623
- if (N->use_empty () || !N->isMachineOpcode ())
2624
- continue ;
2630
+ assert (True.getResNo () == 0 &&
2631
+ " Expect True is the first output of an instruction." );
2625
2632
2626
- auto IsVMergeTU = [](unsigned Opcode) {
2627
- return Opcode == RISCV::PseudoVMERGE_VVM_MF8_TU ||
2628
- Opcode == RISCV::PseudoVMERGE_VVM_MF4_TU ||
2629
- Opcode == RISCV::PseudoVMERGE_VVM_MF2_TU ||
2630
- Opcode == RISCV::PseudoVMERGE_VVM_M1_TU ||
2631
- Opcode == RISCV::PseudoVMERGE_VVM_M2_TU ||
2632
- Opcode == RISCV::PseudoVMERGE_VVM_M4_TU ||
2633
- Opcode == RISCV::PseudoVMERGE_VVM_M8_TU;
2634
- };
2633
+ // Need N is the exactly one using True.
2634
+ if (!True.hasOneUse ())
2635
+ return false ;
2635
2636
2636
- unsigned Opc = N->getMachineOpcode ();
2637
- // TODO: Also deal with TA VMerge nodes.
2638
- if (!IsVMergeTU (Opc))
2639
- continue ;
2637
+ if (!True.isMachineOpcode ())
2638
+ return false ;
2640
2639
2641
- SDValue Merge = N->getOperand (0 );
2642
- SDValue False = N->getOperand (1 );
2643
- SDValue True = N->getOperand (2 );
2644
- SDValue Mask = N->getOperand (3 );
2645
- SDValue VL = N->getOperand (4 );
2640
+ unsigned TrueOpc = True.getMachineOpcode ();
2646
2641
2647
- if (Merge != False)
2648
- continue ;
2642
+ // Skip if True has merge operand.
2643
+ // TODO: Deal with True having same merge operand with N.
2644
+ if (RISCVII::hasMergeOp (TII->get (TrueOpc).TSFlags ))
2645
+ return false ;
2649
2646
2650
- assert (True.getResNo () == 0 &&
2651
- " Expect True is the first output of an instruction." );
2647
+ // Skip if True has side effect.
2648
+ // TODO: Support velff and vlsegff.
2649
+ if (TII->get (TrueOpc).hasUnmodeledSideEffects ())
2650
+ return false ;
2652
2651
2653
- // Need N is the exactly one using True .
2654
- if (!True. hasOneUse ())
2655
- continue ;
2652
+ // Only deal with True when True is unmasked intrinsic now .
2653
+ const RISCV::RISCVMaskedPseudoInfo *Info =
2654
+ RISCV::lookupMaskedIntrinsicByUnmaskedTA (TrueOpc) ;
2656
2655
2657
- if (!True. isMachineOpcode () )
2658
- continue ;
2656
+ if (!Info )
2657
+ return false ;
2659
2658
2660
- unsigned TrueOpc = True.getMachineOpcode ();
2659
+ // The last operand of unmasked intrinsic should be sew or chain.
2660
+ bool HasChainOp =
2661
+ True.getOperand (True.getNumOperands () - 1 ).getValueType () == MVT::Other;
2661
2662
2662
- // Skip if True has merge operand.
2663
- // TODO: Deal with True having same merge operand with N.
2664
- if (RISCVII::hasMergeOp (TII->get (TrueOpc).TSFlags ))
2665
- continue ;
2663
+ // Need True has same VL with N.
2664
+ unsigned TrueVLIndex = True.getNumOperands () - HasChainOp - 2 ;
2665
+ SDValue TrueVL = True.getOperand (TrueVLIndex);
2666
2666
2667
- // Skip if True has side effect.
2668
- // TODO: Support velff and vlsegff.
2669
- if (TII-> get (TrueOpc). hasUnmodeledSideEffects ())
2670
- continue ;
2667
+ auto IsNoFPExcept = [ this ](SDValue N) {
2668
+ return ! this -> mayRaiseFPException (N. getNode ()) ||
2669
+ N-> getFlags (). hasNoFPExcept ();
2670
+ } ;
2671
2671
2672
- // Only deal with True when True is unmasked intrinsic now.
2673
- const RISCV::RISCVMaskedPseudoInfo *Info =
2674
- RISCV::lookupMaskedIntrinsicByUnmaskedTA (TrueOpc);
2672
+ // Allow the peephole for non-exception True with VLMAX vector length, since
2673
+ // all the values after VL of N are dependent on Merge. VLMAX should be
2674
+ // lowered to (XLenVT -1).
2675
+ if (TrueVL != VL && !(IsNoFPExcept (True) && isAllOnesConstant (TrueVL)))
2676
+ return false ;
2675
2677
2676
- if (!Info)
2677
- continue ;
2678
+ SDLoc DL (N);
2679
+ unsigned MaskedOpc = Info->MaskedPseudo ;
2680
+ assert (RISCVII::hasVecPolicyOp (TII->get (MaskedOpc).TSFlags ) &&
2681
+ " Expected instructions with mask have policy operand." );
2678
2682
2679
- // The last operand of unmasked intrinsic should be sew or chain.
2680
- bool HasChainOp =
2681
- True.getOperand (True.getNumOperands () - 1 ).getValueType () == MVT::Other;
2683
+ SmallVector<SDValue, 8 > Ops;
2684
+ Ops.push_back (Merge);
2685
+ Ops.append (True->op_begin (), True->op_begin () + TrueVLIndex);
2686
+ Ops.append ({Mask, VL, /* SEW */ True.getOperand (TrueVLIndex + 1 )});
2687
+ Ops.push_back (
2688
+ CurDAG->getTargetConstant (/* TUMU */ 0 , DL, Subtarget->getXLenVT ()));
2682
2689
2683
- // Need True has same VL with N .
2684
- unsigned TrueVLIndex = True. getNumOperands () - HasChainOp - 2 ;
2685
- SDValue TrueVL = True.getOperand (TrueVLIndex );
2690
+ // Result node should have chain operand of True .
2691
+ if ( HasChainOp)
2692
+ Ops. push_back ( True.getOperand (True. getNumOperands () - 1 ) );
2686
2693
2687
- auto IsNoFPExcept = [this ](SDValue N) {
2688
- return !this ->mayRaiseFPException (N.getNode ()) ||
2689
- N->getFlags ().hasNoFPExcept ();
2690
- };
2694
+ // Result node should take over glued node of N.
2695
+ if (N->getGluedNode ())
2696
+ Ops.push_back (N->getOperand (N->getNumOperands () - 1 ));
2691
2697
2692
- // Allow the peephole for non-exception True with VLMAX vector length, since
2693
- // all the values after VL of N are dependent on Merge. VLMAX should be
2694
- // lowered to (XLenVT -1).
2695
- if (TrueVL != VL && !(IsNoFPExcept (True) && isAllOnesConstant (TrueVL)))
2696
- continue ;
2698
+ SDNode *Result =
2699
+ CurDAG->getMachineNode (MaskedOpc, DL, True->getVTList (), Ops);
2700
+ Result->setFlags (True->getFlags ());
2697
2701
2698
- SDLoc DL (N);
2699
- unsigned MaskedOpc = Info->MaskedPseudo ;
2700
- assert (RISCVII::hasVecPolicyOp (TII->get (MaskedOpc).TSFlags ) &&
2701
- " Expected instructions with mask have policy operand." );
2702
+ // Replace vmerge.vvm node by Result.
2703
+ ReplaceUses (SDValue (N, 0 ), SDValue (Result, 0 ));
2702
2704
2703
- SmallVector<SDValue, 8 > Ops;
2704
- Ops.push_back (Merge);
2705
- Ops.append (True->op_begin (), True->op_begin () + TrueVLIndex);
2706
- Ops.append ({Mask, VL, /* SEW */ True.getOperand (TrueVLIndex + 1 )});
2707
- Ops.push_back (
2708
- CurDAG->getTargetConstant (/* TUMU */ 0 , DL, Subtarget->getXLenVT ()));
2705
+ // Replace another value of True. E.g. chain and VL.
2706
+ for (unsigned Idx = 1 ; Idx < True->getNumValues (); ++Idx)
2707
+ ReplaceUses (True.getValue (Idx), SDValue (Result, Idx));
2709
2708
2710
- // Result node should have chain operand of True.
2711
- if (HasChainOp)
2712
- Ops.push_back (True.getOperand (True.getNumOperands () - 1 ));
2709
+ // Try to transform Result to unmasked intrinsic.
2710
+ doPeepholeMaskedRVV (Result);
2711
+ return true ;
2712
+ }
2713
2713
2714
- // Result node should take over glued node of N.
2715
- if (N->getGluedNode ())
2716
- Ops.push_back (N->getOperand (N->getNumOperands () - 1 ));
2714
+ // Transform (VMERGE_VVM_<LMUL>_TU false, false, true, allones, vl, sew) to
2715
+ // (VADD_VI_<LMUL>_TU false, true, 0, vl, sew). It may decrease uses of VMSET.
2716
+ bool RISCVDAGToDAGISel::performVMergeToVAdd (SDNode *N) {
2717
+ unsigned NewOpc;
2718
+ switch (N->getMachineOpcode ()) {
2719
+ default :
2720
+ llvm_unreachable (" Expected VMERGE_VVM_<LMUL>_TU instruction." );
2721
+ case RISCV::PseudoVMERGE_VVM_MF8_TU:
2722
+ NewOpc = RISCV::PseudoVADD_VI_MF8_TU;
2723
+ break ;
2724
+ case RISCV::PseudoVMERGE_VVM_MF4_TU:
2725
+ NewOpc = RISCV::PseudoVADD_VI_MF4_TU;
2726
+ break ;
2727
+ case RISCV::PseudoVMERGE_VVM_MF2_TU:
2728
+ NewOpc = RISCV::PseudoVADD_VI_MF2_TU;
2729
+ break ;
2730
+ case RISCV::PseudoVMERGE_VVM_M1_TU:
2731
+ NewOpc = RISCV::PseudoVADD_VI_M1_TU;
2732
+ break ;
2733
+ case RISCV::PseudoVMERGE_VVM_M2_TU:
2734
+ NewOpc = RISCV::PseudoVADD_VI_M2_TU;
2735
+ break ;
2736
+ case RISCV::PseudoVMERGE_VVM_M4_TU:
2737
+ NewOpc = RISCV::PseudoVADD_VI_M4_TU;
2738
+ break ;
2739
+ case RISCV::PseudoVMERGE_VVM_M8_TU:
2740
+ NewOpc = RISCV::PseudoVADD_VI_M8_TU;
2741
+ break ;
2742
+ }
2717
2743
2718
- SDNode *Result =
2719
- CurDAG->getMachineNode (MaskedOpc, DL, True->getVTList (), Ops);
2720
- Result->setFlags (True->getFlags ());
2744
+ if (!usesAllOnesMask (N, /* MaskOpIdx */ 3 ))
2745
+ return false ;
2721
2746
2722
- // Replace vmerge.vvm node by Result.
2723
- ReplaceUses (SDValue (N, 0 ), SDValue (Result, 0 ));
2747
+ SDLoc DL (N);
2748
+ EVT VT = N->getValueType (0 );
2749
+ SDValue Ops[] = {N->getOperand (1 ), N->getOperand (2 ),
2750
+ CurDAG->getTargetConstant (0 , DL, Subtarget->getXLenVT ()),
2751
+ N->getOperand (4 ), N->getOperand (5 )};
2752
+ SDNode *Result = CurDAG->getMachineNode (NewOpc, DL, VT, Ops);
2753
+ ReplaceUses (N, Result);
2754
+ return true ;
2755
+ }
2756
+
2757
+ bool RISCVDAGToDAGISel::doPeepholeMergeVVMFold () {
2758
+ bool MadeChange = false ;
2759
+ SelectionDAG::allnodes_iterator Position = CurDAG->allnodes_end ();
2724
2760
2725
- // Replace another value of True. E.g. chain and VL.
2726
- for (unsigned Idx = 1 ; Idx < True->getNumValues (); ++Idx)
2727
- ReplaceUses (True.getValue (Idx), SDValue (Result, Idx));
2761
+ while (Position != CurDAG->allnodes_begin ()) {
2762
+ SDNode *N = &*--Position;
2763
+ if (N->use_empty () || !N->isMachineOpcode ())
2764
+ continue ;
2765
+
2766
+ auto IsVMergeTU = [](unsigned Opcode) {
2767
+ return Opcode == RISCV::PseudoVMERGE_VVM_MF8_TU ||
2768
+ Opcode == RISCV::PseudoVMERGE_VVM_MF4_TU ||
2769
+ Opcode == RISCV::PseudoVMERGE_VVM_MF2_TU ||
2770
+ Opcode == RISCV::PseudoVMERGE_VVM_M1_TU ||
2771
+ Opcode == RISCV::PseudoVMERGE_VVM_M2_TU ||
2772
+ Opcode == RISCV::PseudoVMERGE_VVM_M4_TU ||
2773
+ Opcode == RISCV::PseudoVMERGE_VVM_M8_TU;
2774
+ };
2775
+
2776
+ unsigned Opc = N->getMachineOpcode ();
2777
+ // The following optimizations require that the merge operand of N is same
2778
+ // as the false operand of N.
2779
+ // TODO: Also deal with TA VMerge nodes.
2780
+ if (!IsVMergeTU (Opc) || N->getOperand (0 ) != N->getOperand (1 ))
2781
+ continue ;
2728
2782
2729
- // Try to transform Result to unmasked intrinsic.
2730
- doPeepholeMaskedRVV (Result);
2731
- MadeChange = true ;
2783
+ MadeChange |= performCombineVMergeAndVOps (N);
2784
+ MadeChange |= performVMergeToVAdd (N);
2732
2785
}
2733
2786
return MadeChange;
2734
2787
}
0 commit comments