Skip to content

Commit 44bb0bb

Browse files
committed
[msan] Add handlePairwiseShadowOrIntrinsic and use it to handle Arm NEON pairwise add
This adds a function, handlePairwiseShadowOrIntrinsic, that propagates shadow for 1- or 2-vector intrinsics that combine adjacent fields, by OR'ing the corresponding adjacent shadows. It then applies it to Arm NEON pairwise add: llvm.aarch64.neon.{addhn, raddhn} (currently incorrectly handled) and llvm.aarch64.neon.{saddlp, uaddlp} (currently suboptimally handled). Updates the tests from #125820
1 parent 99099cd commit 44bb0bb

File tree

3 files changed

+289
-259
lines changed

3 files changed

+289
-259
lines changed

llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2602,6 +2602,57 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
26022602
SC.Done(&I);
26032603
}
26042604

2605+
/// Propagate shadow for 1- or 2-vector intrinsics that combine adjacent
2606+
/// fields.
2607+
///
2608+
/// e.g., <2 x i32> @llvm.aarch64.neon.saddlp.v2i32.v4i16(<4 x i16>)
2609+
/// <16 x i8> @llvm.aarch64.neon.addp.v16i8(<16 x i8>, <16 x i8>)
2610+
///
2611+
/// TODO: adapt this function to handle horizontal add/sub?
2612+
void handlePairwiseShadowOrIntrinsic(IntrinsicInst &I) {
2613+
assert(I.arg_size() == 1 || I.arg_size() == 2);
2614+
2615+
assert(I.getType()->isVectorTy());
2616+
assert(I.getArgOperand(0)->getType()->isVectorTy());
2617+
2618+
FixedVectorType *ParamType =
2619+
cast<FixedVectorType>(I.getArgOperand(0)->getType());
2620+
if (I.arg_size() == 2)
2621+
assert(ParamType == cast<FixedVectorType>(I.getArgOperand(1)->getType()));
2622+
FixedVectorType *ReturnType = cast<FixedVectorType>(I.getType());
2623+
assert(ParamType->getNumElements() * I.arg_size() ==
2624+
2 * ReturnType->getNumElements());
2625+
2626+
IRBuilder<> IRB(&I);
2627+
unsigned Width = ParamType->getNumElements() * I.arg_size();
2628+
2629+
// Horizontal OR of shadow
2630+
SmallVector<int, 8> EvenMask;
2631+
SmallVector<int, 8> OddMask;
2632+
for (unsigned X = 0; X < Width; X += 2) {
2633+
EvenMask.append(1, X);
2634+
OddMask.append(1, X + 1);
2635+
}
2636+
2637+
Value *EvenShadow;
2638+
Value *OddShadow;
2639+
if (I.arg_size() == 2) {
2640+
EvenShadow =
2641+
IRB.CreateShuffleVector(getShadow(&I, 0), getShadow(&I, 1), EvenMask);
2642+
OddShadow =
2643+
IRB.CreateShuffleVector(getShadow(&I, 0), getShadow(&I, 1), OddMask);
2644+
} else {
2645+
EvenShadow = IRB.CreateShuffleVector(getShadow(&I, 0), EvenMask);
2646+
OddShadow = IRB.CreateShuffleVector(getShadow(&I, 0), OddMask);
2647+
}
2648+
2649+
Value *OrShadow = IRB.CreateOr(EvenShadow, OddShadow);
2650+
OrShadow = CreateShadowCast(IRB, OrShadow, getShadowTy(&I));
2651+
2652+
setShadow(&I, OrShadow);
2653+
setOriginForNaryOp(I);
2654+
}
2655+
26052656
void visitFNeg(UnaryOperator &I) { handleShadowOr(I); }
26062657

26072658
// Handle multiplication by constant.
@@ -4781,6 +4832,17 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
47814832
setOrigin(&I, getCleanOrigin());
47824833
break;
47834834

4835+
// Add Pairwise
4836+
case Intrinsic::aarch64_neon_addp:
4837+
// Floating-point Add Pairwise
4838+
case Intrinsic::aarch64_neon_faddp:
4839+
// Add Long Pairwise
4840+
case Intrinsic::aarch64_neon_saddlp:
4841+
case Intrinsic::aarch64_neon_uaddlp: {
4842+
handlePairwiseShadowOrIntrinsic(I);
4843+
break;
4844+
}
4845+
47844846
case Intrinsic::aarch64_neon_st1x2:
47854847
case Intrinsic::aarch64_neon_st1x3:
47864848
case Intrinsic::aarch64_neon_st1x4:

0 commit comments

Comments
 (0)