@@ -2690,6 +2690,54 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
26902690 SC.Done (&I);
26912691 }
26922692
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+
26932741 // / Propagate shadow for 1- or 2-vector intrinsics that combine adjacent
26942742 // / fields.
26952743 // /
@@ -2711,31 +2759,16 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
27112759 2 * ReturnType->getNumElements ());
27122760
27132761 IRBuilder<> IRB (&I);
2714- unsigned Width = ParamType->getNumElements () * I.arg_size ();
27152762
27162763 // 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-
27242764 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);
27372771
2738- Value *OrShadow = IRB.CreateOr (EvenShadow, OddShadow);
27392772 OrShadow = CreateShadowCast (IRB, OrShadow, getShadowTy (&I));
27402773
27412774 setShadow (&I, OrShadow);
@@ -2768,23 +2801,14 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
27682801
27692802 IRBuilder<> IRB (&I);
27702803
2771- unsigned TotalNumElems = ParamType->getNumElements () * I.arg_size ();
27722804 FixedVectorType *ReinterpretShadowTy = nullptr ;
27732805 assert (isAligned (Align (ReinterpretElemWidth),
27742806 ParamType->getPrimitiveSizeInBits ()));
27752807 ReinterpretShadowTy = FixedVectorType::get (
27762808 IRB.getIntNTy (ReinterpretElemWidth),
27772809 ParamType->getPrimitiveSizeInBits () / ReinterpretElemWidth);
2778- TotalNumElems = ReinterpretShadowTy->getNumElements () * I.arg_size ();
27792810
27802811 // 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-
27882812 Value *FirstArgShadow = getShadow (&I, 0 );
27892813 FirstArgShadow = IRB.CreateBitCast (FirstArgShadow, ReinterpretShadowTy);
27902814
@@ -2796,22 +2820,15 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
27962820 Align (2 ),
27972821 cast<FixedVectorType>(FirstArgShadow->getType ())->getNumElements ()));
27982822
2799- Value *EvenShadow;
2800- Value *OddShadow;
2823+ Value *SecondArgShadow = nullptr ;
28012824 if (I.arg_size () == 2 ) {
2802- Value * SecondArgShadow = getShadow (&I, 1 );
2825+ SecondArgShadow = getShadow (&I, 1 );
28032826 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);
28122827 }
28132828
2814- Value *OrShadow = IRB.CreateOr (EvenShadow, OddShadow);
2829+ Value *OrShadow = horizontalReduce (I, /* ReductionFactor=*/ 2 , FirstArgShadow,
2830+ SecondArgShadow);
2831+
28152832 OrShadow = CreateShadowCast (IRB, OrShadow, getShadowTy (&I));
28162833
28172834 setShadow (&I, OrShadow);
@@ -3219,7 +3236,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
32193236 // / Caller guarantees that this intrinsic does not access memory.
32203237 // /
32213238 // / TODO: "horizontal"/"pairwise" intrinsics are often incorrectly matched by
3222- // / by this handler.
3239+ // / by this handler. See horizontalReduce().
32233240 [[maybe_unused]] bool
32243241 maybeHandleSimpleNomemIntrinsic (IntrinsicInst &I,
32253242 unsigned int trailingFlags) {
0 commit comments