@@ -537,6 +537,7 @@ class VPSingleDefRecipe : public VPRecipeBase, public VPValue {
537
537
case VPRecipeBase::VPBranchOnMaskSC:
538
538
case VPRecipeBase::VPInterleaveSC:
539
539
case VPRecipeBase::VPIRInstructionSC:
540
+ case VPRecipeBase::VPWidenStridedLoadSC:
540
541
case VPRecipeBase::VPWidenLoadEVLSC:
541
542
case VPRecipeBase::VPWidenLoadSC:
542
543
case VPRecipeBase::VPWidenStoreEVLSC:
@@ -2567,9 +2568,6 @@ class VPWidenMemoryRecipe : public VPRecipeBase {
2567
2568
// / Whether the consecutive accessed addresses are in reverse order.
2568
2569
bool Reverse;
2569
2570
2570
- // / Whether the accessed addresses are evenly spaced apart by a fixed stride.
2571
- bool Strided = false ;
2572
-
2573
2571
// / Whether the memory access is masked.
2574
2572
bool IsMasked = false ;
2575
2573
@@ -2583,9 +2581,9 @@ class VPWidenMemoryRecipe : public VPRecipeBase {
2583
2581
2584
2582
VPWidenMemoryRecipe (const char unsigned SC, Instruction &I,
2585
2583
std::initializer_list<VPValue *> Operands,
2586
- bool Consecutive, bool Reverse, bool Strided, DebugLoc DL)
2584
+ bool Consecutive, bool Reverse, DebugLoc DL)
2587
2585
: VPRecipeBase(SC, Operands, DL), Ingredient(I), Consecutive(Consecutive),
2588
- Reverse (Reverse), Strided(Strided) {
2586
+ Reverse (Reverse) {
2589
2587
assert ((Consecutive || !Reverse) && " Reverse implies consecutive" );
2590
2588
}
2591
2589
@@ -2598,7 +2596,8 @@ class VPWidenMemoryRecipe : public VPRecipeBase {
2598
2596
return R->getVPDefID () == VPRecipeBase::VPWidenLoadSC ||
2599
2597
R->getVPDefID () == VPRecipeBase::VPWidenStoreSC ||
2600
2598
R->getVPDefID () == VPRecipeBase::VPWidenLoadEVLSC ||
2601
- R->getVPDefID () == VPRecipeBase::VPWidenStoreEVLSC;
2599
+ R->getVPDefID () == VPRecipeBase::VPWidenStoreEVLSC ||
2600
+ R->getVPDefID () == VPRecipeBase::VPWidenStridedLoadSC;
2602
2601
}
2603
2602
2604
2603
static inline bool classof (const VPUser *U) {
@@ -2613,10 +2612,6 @@ class VPWidenMemoryRecipe : public VPRecipeBase {
2613
2612
// / order.
2614
2613
bool isReverse () const { return Reverse; }
2615
2614
2616
- // / Return whether the accessed addresses are evenly spaced apart by a fixed
2617
- // / stride.
2618
- bool isStrided () const { return Strided; }
2619
-
2620
2615
// / Return the address accessed by this recipe.
2621
2616
VPValue *getAddr () const { return getOperand (0 ); }
2622
2617
@@ -2646,16 +2641,16 @@ class VPWidenMemoryRecipe : public VPRecipeBase {
2646
2641
// / optional mask.
2647
2642
struct VPWidenLoadRecipe final : public VPWidenMemoryRecipe, public VPValue {
2648
2643
VPWidenLoadRecipe (LoadInst &Load, VPValue *Addr, VPValue *Mask,
2649
- bool Consecutive, bool Reverse, bool Strided, DebugLoc DL)
2644
+ bool Consecutive, bool Reverse, DebugLoc DL)
2650
2645
: VPWidenMemoryRecipe(VPDef::VPWidenLoadSC, Load, {Addr}, Consecutive,
2651
- Reverse, Strided, DL),
2646
+ Reverse, DL),
2652
2647
VPValue (this , &Load) {
2653
2648
setMask (Mask);
2654
2649
}
2655
2650
2656
2651
VPWidenLoadRecipe *clone () override {
2657
2652
return new VPWidenLoadRecipe (cast<LoadInst>(Ingredient), getAddr (),
2658
- getMask (), Consecutive, Reverse, Strided,
2653
+ getMask (), Consecutive, Reverse,
2659
2654
getDebugLoc ());
2660
2655
}
2661
2656
@@ -2674,9 +2669,9 @@ struct VPWidenLoadRecipe final : public VPWidenMemoryRecipe, public VPValue {
2674
2669
bool onlyFirstLaneUsed (const VPValue *Op) const override {
2675
2670
assert (is_contained (operands (), Op) &&
2676
2671
" Op must be an operand of the recipe" );
2677
- // Widened, consecutive/strided loads operations only demand the first
2678
- // lane of their address.
2679
- return Op == getAddr () && ( isConsecutive () || isStrided () );
2672
+ // Widened, consecutive loads operations only demand the first lane of their
2673
+ // address.
2674
+ return Op == getAddr () && isConsecutive ();
2680
2675
}
2681
2676
};
2682
2677
@@ -2687,7 +2682,7 @@ struct VPWidenLoadEVLRecipe final : public VPWidenMemoryRecipe, public VPValue {
2687
2682
VPWidenLoadEVLRecipe (VPWidenLoadRecipe &L, VPValue &EVL, VPValue *Mask)
2688
2683
: VPWidenMemoryRecipe(VPDef::VPWidenLoadEVLSC, L.getIngredient(),
2689
2684
{L.getAddr (), &EVL}, L.isConsecutive(),
2690
- L.isReverse(), L.isStrided(), L. getDebugLoc()),
2685
+ L.isReverse(), L.getDebugLoc()),
2691
2686
VPValue (this , &getIngredient ()) {
2692
2687
setMask (Mask);
2693
2688
}
@@ -2716,26 +2711,72 @@ struct VPWidenLoadEVLRecipe final : public VPWidenMemoryRecipe, public VPValue {
2716
2711
" Op must be an operand of the recipe" );
2717
2712
// Widened loads only demand the first lane of EVL and consecutive/strided
2718
2713
// loads only demand the first lane of their address.
2719
- return Op == getEVL () ||
2720
- (Op == getAddr () && (isConsecutive () || isStrided ()));
2714
+ return Op == getEVL () || (Op == getAddr () && isConsecutive ());
2715
+ }
2716
+ };
2717
+
2718
+ // / A recipe for strided load operations, using the base address, stride, and an
2719
+ // / optional mask.
2720
+ struct VPWidenStridedLoadRecipe final : public VPWidenMemoryRecipe,
2721
+ public VPValue {
2722
+ VPWidenStridedLoadRecipe (LoadInst &Load, VPValue *Addr, VPValue *Stride,
2723
+ VPValue *VF, VPValue *Mask, DebugLoc DL)
2724
+ : VPWidenMemoryRecipe(VPDef::VPWidenStridedLoadSC, Load,
2725
+ {Addr, Stride, VF},
2726
+ /* Consecutive=*/ false , /* Reverse=*/ false , DL),
2727
+ VPValue (this , &Load) {
2728
+ setMask (Mask);
2729
+ }
2730
+
2731
+ VPWidenStridedLoadRecipe *clone () override {
2732
+ return new VPWidenStridedLoadRecipe (cast<LoadInst>(Ingredient), getAddr (),
2733
+ getStride (), getVF (), getMask (),
2734
+ getDebugLoc ());
2735
+ }
2736
+
2737
+ VP_CLASSOF_IMPL (VPDef::VPWidenStridedLoadSC);
2738
+
2739
+ // / Return the stride operand.
2740
+ VPValue *getStride () const { return getOperand (1 ); }
2741
+
2742
+ // / Return the VF operand.
2743
+ VPValue *getVF () const { return getOperand (2 ); }
2744
+
2745
+ // / Generate a strided load.
2746
+ void execute (VPTransformState &State) override ;
2747
+
2748
+ // / Return the cost of this VPWidenStridedLoadRecipe.
2749
+ InstructionCost computeCost (ElementCount VF,
2750
+ VPCostContext &Ctx) const override ;
2751
+
2752
+ #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2753
+ // / Print the recipe.
2754
+ void print (raw_ostream &O, const Twine &Indent,
2755
+ VPSlotTracker &SlotTracker) const override ;
2756
+ #endif
2757
+
2758
+ // / Returns true if the recipe only uses the first lane of operand \p Op.
2759
+ bool onlyFirstLaneUsed (const VPValue *Op) const override {
2760
+ assert (is_contained (operands (), Op) &&
2761
+ " Op must be an operand of the recipe" );
2762
+ return Op == getAddr () || Op == getStride () || Op == getVF ();
2721
2763
}
2722
2764
};
2723
2765
2724
2766
// / A recipe for widening store operations, using the stored value, the address
2725
2767
// / to store to and an optional mask.
2726
2768
struct VPWidenStoreRecipe final : public VPWidenMemoryRecipe {
2727
2769
VPWidenStoreRecipe (StoreInst &Store, VPValue *Addr, VPValue *StoredVal,
2728
- VPValue *Mask, bool Consecutive, bool Reverse,
2729
- bool Strided, DebugLoc DL)
2770
+ VPValue *Mask, bool Consecutive, bool Reverse, DebugLoc DL)
2730
2771
: VPWidenMemoryRecipe(VPDef::VPWidenStoreSC, Store, {Addr, StoredVal},
2731
- Consecutive, Reverse, Strided, DL) {
2772
+ Consecutive, Reverse, DL) {
2732
2773
setMask (Mask);
2733
2774
}
2734
2775
2735
2776
VPWidenStoreRecipe *clone () override {
2736
2777
return new VPWidenStoreRecipe (cast<StoreInst>(Ingredient), getAddr (),
2737
2778
getStoredValue (), getMask (), Consecutive,
2738
- Reverse, Strided, getDebugLoc ());
2779
+ Reverse, getDebugLoc ());
2739
2780
}
2740
2781
2741
2782
VP_CLASSOF_IMPL (VPDef::VPWidenStoreSC);
@@ -2756,10 +2797,9 @@ struct VPWidenStoreRecipe final : public VPWidenMemoryRecipe {
2756
2797
bool onlyFirstLaneUsed (const VPValue *Op) const override {
2757
2798
assert (is_contained (operands (), Op) &&
2758
2799
" Op must be an operand of the recipe" );
2759
- // Widened, consecutive/strided stores only demand the first lane of their
2800
+ // Widened, consecutive stores only demand the first lane of their
2760
2801
// address, unless the same operand is also stored.
2761
- return Op == getAddr () && (isConsecutive () || isStrided ()) &&
2762
- Op != getStoredValue ();
2802
+ return Op == getAddr () && isConsecutive () && Op != getStoredValue ();
2763
2803
}
2764
2804
};
2765
2805
@@ -2770,8 +2810,7 @@ struct VPWidenStoreEVLRecipe final : public VPWidenMemoryRecipe {
2770
2810
VPWidenStoreEVLRecipe (VPWidenStoreRecipe &S, VPValue &EVL, VPValue *Mask)
2771
2811
: VPWidenMemoryRecipe(VPDef::VPWidenStoreEVLSC, S.getIngredient(),
2772
2812
{S.getAddr (), S.getStoredValue (), &EVL},
2773
- S.isConsecutive(), S.isReverse(), S.isStrided(),
2774
- S.getDebugLoc()) {
2813
+ S.isConsecutive(), S.isReverse(), S.getDebugLoc()) {
2775
2814
setMask (Mask);
2776
2815
}
2777
2816
@@ -2804,11 +2843,10 @@ struct VPWidenStoreEVLRecipe final : public VPWidenMemoryRecipe {
2804
2843
assert (getStoredValue () != Op && " unexpected store of EVL" );
2805
2844
return true ;
2806
2845
}
2807
- // Widened, consecutive/strided memory operations only demand the first lane
2808
- // of their address, unless the same operand is also stored. That latter can
2846
+ // Widened, consecutive memory operations only demand the first lane of
2847
+ // their address, unless the same operand is also stored. That latter can
2809
2848
// happen with opaque pointers.
2810
- return Op == getAddr () && (isConsecutive () || isStrided ()) &&
2811
- Op != getStoredValue ();
2849
+ return Op == getAddr () && isConsecutive () && Op != getStoredValue ();
2812
2850
}
2813
2851
};
2814
2852
0 commit comments