@@ -2690,6 +2690,54 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
2690
2690
SC.Done (&I);
2691
2691
}
2692
2692
2693
+ // Perform a bitwise OR on the horizontal pairs (or other specified grouping)
2694
+ // of elements.
2695
+ //
2696
+ // For example, suppose we have:
2697
+ // VectorA: <a1, a2, a3, a4, a5, a6>
2698
+ // VectorB: <b1, b2, b3, b4, b5, b6>
2699
+ // ReductionFactor: 3.
2700
+ // The output would be:
2701
+ // <a1|a2|a3, a4|a5|a6, b1|b2|b3, b4|b5|b6>
2702
+ //
2703
+ // This is convenient for instrumenting horizontal add/sub.
2704
+ // For bitwise OR on "vertical" pairs, see maybeHandleSimpleNomemIntrinsic().
2705
+ Value *horizontalReduce (IntrinsicInst &I, unsigned ReductionFactor,
2706
+ Value *VectorA, Value *VectorB) {
2707
+ assert (isa<FixedVectorType>(VectorA->getType ()));
2708
+ unsigned TotalNumElems =
2709
+ cast<FixedVectorType>(VectorA->getType ())->getNumElements ();
2710
+
2711
+ if (VectorB) {
2712
+ assert (VectorA->getType () == VectorB->getType ());
2713
+ TotalNumElems = TotalNumElems * 2 ;
2714
+ }
2715
+
2716
+ assert (TotalNumElems % ReductionFactor == 0 );
2717
+
2718
+ Value *Or = nullptr ;
2719
+
2720
+ IRBuilder<> IRB (&I);
2721
+ for (unsigned i = 0 ; i < ReductionFactor; i++) {
2722
+ SmallVector<int , 16 > Mask;
2723
+ for (unsigned X = 0 ; X < TotalNumElems; X += ReductionFactor)
2724
+ Mask.push_back (X + i);
2725
+
2726
+ Value *Masked;
2727
+ if (VectorB)
2728
+ Masked = IRB.CreateShuffleVector (VectorA, VectorB, Mask);
2729
+ else
2730
+ Masked = IRB.CreateShuffleVector (VectorA, Mask);
2731
+
2732
+ if (Or)
2733
+ Or = IRB.CreateOr (Or, Masked);
2734
+ else
2735
+ Or = Masked;
2736
+ }
2737
+
2738
+ return Or;
2739
+ }
2740
+
2693
2741
// / Propagate shadow for 1- or 2-vector intrinsics that combine adjacent
2694
2742
// / fields.
2695
2743
// /
@@ -2711,31 +2759,16 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
2711
2759
2 * ReturnType->getNumElements ());
2712
2760
2713
2761
IRBuilder<> IRB (&I);
2714
- unsigned Width = ParamType->getNumElements () * I.arg_size ();
2715
2762
2716
2763
// Horizontal OR of shadow
2717
- SmallVector<int , 8 > EvenMask;
2718
- SmallVector<int , 8 > OddMask;
2719
- for (unsigned X = 0 ; X < Width; X += 2 ) {
2720
- EvenMask.push_back (X);
2721
- OddMask.push_back (X + 1 );
2722
- }
2723
-
2724
2764
Value *FirstArgShadow = getShadow (&I, 0 );
2725
- Value *EvenShadow;
2726
- Value *OddShadow;
2727
- if (I.arg_size () == 2 ) {
2728
- Value *SecondArgShadow = getShadow (&I, 1 );
2729
- EvenShadow =
2730
- IRB.CreateShuffleVector (FirstArgShadow, SecondArgShadow, EvenMask);
2731
- OddShadow =
2732
- IRB.CreateShuffleVector (FirstArgShadow, SecondArgShadow, OddMask);
2733
- } else {
2734
- EvenShadow = IRB.CreateShuffleVector (FirstArgShadow, EvenMask);
2735
- OddShadow = IRB.CreateShuffleVector (FirstArgShadow, OddMask);
2736
- }
2765
+ Value *SecondArgShadow = nullptr ;
2766
+ if (I.arg_size () == 2 )
2767
+ SecondArgShadow = getShadow (&I, 1 );
2768
+
2769
+ Value *OrShadow = horizontalReduce (I, /* ReductionFactor=*/ 2 , FirstArgShadow,
2770
+ SecondArgShadow);
2737
2771
2738
- Value *OrShadow = IRB.CreateOr (EvenShadow, OddShadow);
2739
2772
OrShadow = CreateShadowCast (IRB, OrShadow, getShadowTy (&I));
2740
2773
2741
2774
setShadow (&I, OrShadow);
@@ -2768,23 +2801,14 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
2768
2801
2769
2802
IRBuilder<> IRB (&I);
2770
2803
2771
- unsigned TotalNumElems = ParamType->getNumElements () * I.arg_size ();
2772
2804
FixedVectorType *ReinterpretShadowTy = nullptr ;
2773
2805
assert (isAligned (Align (ReinterpretElemWidth),
2774
2806
ParamType->getPrimitiveSizeInBits ()));
2775
2807
ReinterpretShadowTy = FixedVectorType::get (
2776
2808
IRB.getIntNTy (ReinterpretElemWidth),
2777
2809
ParamType->getPrimitiveSizeInBits () / ReinterpretElemWidth);
2778
- TotalNumElems = ReinterpretShadowTy->getNumElements () * I.arg_size ();
2779
2810
2780
2811
// Horizontal OR of shadow
2781
- SmallVector<int , 8 > EvenMask;
2782
- SmallVector<int , 8 > OddMask;
2783
- for (unsigned X = 0 ; X < TotalNumElems - 1 ; X += 2 ) {
2784
- EvenMask.push_back (X);
2785
- OddMask.push_back (X + 1 );
2786
- }
2787
-
2788
2812
Value *FirstArgShadow = getShadow (&I, 0 );
2789
2813
FirstArgShadow = IRB.CreateBitCast (FirstArgShadow, ReinterpretShadowTy);
2790
2814
@@ -2796,22 +2820,15 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
2796
2820
Align (2 ),
2797
2821
cast<FixedVectorType>(FirstArgShadow->getType ())->getNumElements ()));
2798
2822
2799
- Value *EvenShadow;
2800
- Value *OddShadow;
2823
+ Value *SecondArgShadow = nullptr ;
2801
2824
if (I.arg_size () == 2 ) {
2802
- Value * SecondArgShadow = getShadow (&I, 1 );
2825
+ SecondArgShadow = getShadow (&I, 1 );
2803
2826
SecondArgShadow = IRB.CreateBitCast (SecondArgShadow, ReinterpretShadowTy);
2804
-
2805
- EvenShadow =
2806
- IRB.CreateShuffleVector (FirstArgShadow, SecondArgShadow, EvenMask);
2807
- OddShadow =
2808
- IRB.CreateShuffleVector (FirstArgShadow, SecondArgShadow, OddMask);
2809
- } else {
2810
- EvenShadow = IRB.CreateShuffleVector (FirstArgShadow, EvenMask);
2811
- OddShadow = IRB.CreateShuffleVector (FirstArgShadow, OddMask);
2812
2827
}
2813
2828
2814
- Value *OrShadow = IRB.CreateOr (EvenShadow, OddShadow);
2829
+ Value *OrShadow = horizontalReduce (I, /* ReductionFactor=*/ 2 , FirstArgShadow,
2830
+ SecondArgShadow);
2831
+
2815
2832
OrShadow = CreateShadowCast (IRB, OrShadow, getShadowTy (&I));
2816
2833
2817
2834
setShadow (&I, OrShadow);
@@ -3219,7 +3236,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
3219
3236
// / Caller guarantees that this intrinsic does not access memory.
3220
3237
// /
3221
3238
// / TODO: "horizontal"/"pairwise" intrinsics are often incorrectly matched by
3222
- // / by this handler.
3239
+ // / by this handler. See horizontalReduce().
3223
3240
[[maybe_unused]] bool
3224
3241
maybeHandleSimpleNomemIntrinsic (IntrinsicInst &I,
3225
3242
unsigned int trailingFlags) {
0 commit comments